Implement ABI release fops and teardown paths
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 25 Nov 2010 02:19:06 +0000 (21:19 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 25 Nov 2010 02:19:06 +0000 (21:19 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
ltt-debugfs-abi.c

index d9d93ac4f0dac131f556f99f739e6f8769c06afc..1e3adfa1c4b3c3518442ccacd6939803f43bed27 100644 (file)
@@ -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]",
                                          &lttng_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]",
                                       &lttng_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]",
-                                        &lttng_event_fops,
-                                        event, O_RDWR);
+                                       &lttng_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
 }
 
This page took 0.029927 seconds and 4 git commands to generate.