X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttng-abi.c;h=1f00a0e5427aca5111bd625bc9193992269d406c;hb=refs%2Fheads%2Fstable-2.9;hp=d4c5ea0fc8938d1d31b6639357546b24a5d19ffa;hpb=f127e61ee231d002fb9a7803643a157e06f6d2e2;p=lttng-modules.git diff --git a/lttng-abi.c b/lttng-abi.c index d4c5ea0f..1f00a0e5 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -44,17 +44,19 @@ #include #include #include -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ -#include "wrapper/ringbuffer/vfs.h" -#include "wrapper/ringbuffer/backend.h" -#include "wrapper/ringbuffer/frontend.h" -#include "wrapper/poll.h" -#include "wrapper/file.h" -#include "lttng-abi.h" -#include "lttng-abi-old.h" -#include "lttng-events.h" -#include "lttng-tracer.h" -#include "lib/ringbuffer/frontend_types.h" +#include /* for wrapper_vmalloc_sync_all() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* * This is LTTng's own personal way to create a system call as an external @@ -69,6 +71,8 @@ static const struct file_operations lttng_metadata_fops; static const struct file_operations lttng_event_fops; static struct file_operations lttng_stream_ring_buffer_file_operations; +static int put_u64(uint64_t val, unsigned long arg); + /* * Teardown management: opened file descriptors keep a refcount on the module, * so it can only exit when all file descriptors are closed. @@ -130,10 +134,6 @@ int lttng_abi_tracepoint_list(void) if (ret < 0) goto open_error; fd_install(file_fd, tracepoint_list_file); - if (file_fd < 0) { - ret = file_fd; - goto fd_error; - } return file_fd; open_error: @@ -174,10 +174,6 @@ int lttng_abi_syscall_list(void) if (ret < 0) goto open_error; fd_install(file_fd, syscall_list_file); - if (file_fd < 0) { - ret = file_fd; - goto fd_error; - } return file_fd; open_error: @@ -240,6 +236,16 @@ long lttng_abi_add_context(struct file *file, return lttng_add_procname_to_ctx(ctx); case LTTNG_KERNEL_CONTEXT_HOSTNAME: return lttng_add_hostname_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_CPU_ID: + return lttng_add_cpu_id_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE: + return lttng_add_interruptible_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE: + return lttng_add_need_reschedule_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_PREEMPTIBLE: + return lttng_add_preemptible_to_ctx(ctx); + case LTTNG_KERNEL_CONTEXT_MIGRATABLE: + return lttng_add_migratable_to_ctx(ctx); default: return -EINVAL; } @@ -423,6 +429,10 @@ int lttng_abi_create_channel(struct file *session_file, transport_name = ""; break; } + if (!atomic_long_add_unless(&session_file->f_count, 1, LONG_MAX)) { + ret = -EOVERFLOW; + goto refcount_error; + } /* * We tolerate no failure path after channel creation. It will stay * invariant for the rest of the session. @@ -440,11 +450,12 @@ int lttng_abi_create_channel(struct file *session_file, chan->file = chan_file; chan_file->private_data = chan; fd_install(chan_fd, chan_file); - atomic_long_inc(&session_file->f_count); return chan_fd; chan_error: + atomic_long_dec(&session_file->f_count); +refcount_error: fput(chan_file); file_error: put_unused_fd(chan_fd); @@ -479,13 +490,12 @@ static long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct lttng_session *session = file->private_data; + struct lttng_kernel_channel chan_param; + struct lttng_kernel_old_channel old_chan_param; switch (cmd) { case LTTNG_KERNEL_OLD_CHANNEL: { - struct lttng_kernel_channel chan_param; - struct lttng_kernel_old_channel old_chan_param; - if (copy_from_user(&old_chan_param, (struct lttng_kernel_old_channel __user *) arg, sizeof(struct lttng_kernel_old_channel))) @@ -502,8 +512,6 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case LTTNG_KERNEL_CHANNEL: { - struct lttng_kernel_channel chan_param; - if (copy_from_user(&chan_param, (struct lttng_kernel_channel __user *) arg, sizeof(struct lttng_kernel_channel))) @@ -523,9 +531,6 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_session_disable(session); case LTTNG_KERNEL_OLD_METADATA: { - struct lttng_kernel_channel chan_param; - struct lttng_kernel_old_channel old_chan_param; - if (copy_from_user(&old_chan_param, (struct lttng_kernel_old_channel __user *) arg, sizeof(struct lttng_kernel_old_channel))) @@ -542,8 +547,6 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case LTTNG_KERNEL_METADATA: { - struct lttng_kernel_channel chan_param; - if (copy_from_user(&chan_param, (struct lttng_kernel_channel __user *) arg, sizeof(struct lttng_kernel_channel))) @@ -557,6 +560,10 @@ long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_session_untrack_pid(session, (int) arg); case LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS: return lttng_session_list_tracker_pids(session); + case LTTNG_KERNEL_SESSION_METADATA_REGEN: + return lttng_session_metadata_regenerate(session); + case LTTNG_KERNEL_SESSION_STATEDUMP: + return lttng_session_statedump(session); default: return -ENOIOCTLCMD; } @@ -620,9 +627,11 @@ unsigned int lttng_metadata_ring_buffer_poll(struct file *filp, if (finalized) mask |= POLLHUP; + mutex_lock(&stream->metadata_cache->lock); if (stream->metadata_cache->metadata_written > stream->metadata_out) mask |= POLLIN; + mutex_unlock(&stream->metadata_cache->lock); } return mask; @@ -667,6 +676,7 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp, */ return -ENOSYS; } + case RING_BUFFER_FLUSH_EMPTY: /* Fall-through. */ case RING_BUFFER_FLUSH: { struct lttng_metadata_stream *stream = filp->private_data; @@ -682,6 +692,12 @@ long lttng_metadata_ring_buffer_ioctl(struct file *filp, goto err; break; } + case RING_BUFFER_GET_METADATA_VERSION: + { + struct lttng_metadata_stream *stream = filp->private_data; + + return put_u64(stream->version, arg); + } default: break; } @@ -737,6 +753,28 @@ long lttng_metadata_ring_buffer_compat_ioctl(struct file *filp, */ return -ENOSYS; } + case RING_BUFFER_FLUSH_EMPTY: /* Fall-through. */ + case RING_BUFFER_FLUSH: + { + struct lttng_metadata_stream *stream = filp->private_data; + struct lib_ring_buffer *buf = stream->priv; + struct channel *chan = buf->backend.chan; + + /* + * Before doing the actual ring buffer flush, write up to one + * packet of metadata in the ring buffer. + */ + ret = lttng_metadata_output_channel(stream, chan); + if (ret < 0) + goto err; + break; + } + case RING_BUFFER_GET_METADATA_VERSION: + { + struct lttng_metadata_stream *stream = filp->private_data; + + return put_u64(stream->version, arg); + } default: break; } @@ -920,7 +958,6 @@ int lttng_abi_open_metadata_stream(struct file *channel_file) metadata_stream->priv = buf; stream_priv = metadata_stream; metadata_stream->transport = channel->transport; - mutex_init(&metadata_stream->lock); /* * Since life-time of metadata cache differs from that of @@ -932,17 +969,23 @@ int lttng_abi_open_metadata_stream(struct file *channel_file) goto notransport; } + if (!lttng_kref_get(&session->metadata_cache->refcount)) { + ret = -EOVERFLOW; + goto kref_error; + } + ret = lttng_abi_create_stream_fd(channel_file, stream_priv, <tng_metadata_ring_buffer_file_operations); if (ret < 0) goto fd_error; - kref_get(&session->metadata_cache->refcount); list_add(&metadata_stream->list, &session->metadata_cache->metadata_stream); return ret; fd_error: + kref_put(&session->metadata_cache->refcount, metadata_cache_destroy); +kref_error: module_put(metadata_stream->transport->owner); notransport: kfree(metadata_stream); @@ -986,6 +1029,11 @@ int lttng_abi_create_event(struct file *channel_file, ret = PTR_ERR(event_file); goto file_error; } + /* The event holds a reference on the channel */ + if (!atomic_long_add_unless(&channel_file->f_count, 1, LONG_MAX)) { + ret = -EOVERFLOW; + goto refcount_error; + } if (event_param->instrumentation == LTTNG_KERNEL_TRACEPOINT || event_param->instrumentation == LTTNG_KERNEL_SYSCALL) { struct lttng_enabler *enabler; @@ -1017,11 +1065,11 @@ int lttng_abi_create_event(struct file *channel_file, } event_file->private_data = priv; fd_install(event_fd, event_file); - /* The event holds a reference on the channel */ - atomic_long_inc(&channel_file->f_count); return event_fd; event_error: + atomic_long_dec(&channel_file->f_count); +refcount_error: fput(event_file); file_error: put_unused_fd(event_fd); @@ -1283,8 +1331,8 @@ int lttng_metadata_channel_release(struct inode *inode, struct file *file) struct lttng_channel *channel = file->private_data; if (channel) { - lttng_metadata_channel_destroy(channel); fput(channel->session->file); + lttng_metadata_channel_destroy(channel); } return 0; @@ -1505,6 +1553,24 @@ static long lttng_stream_ring_buffer_ioctl(struct file *filp, goto error; return put_u64(ts, arg); } + case LTTNG_RING_BUFFER_GET_SEQ_NUM: + { + uint64_t seq; + + ret = ops->sequence_number(config, buf, &seq); + if (ret < 0) + goto error; + return put_u64(seq, arg); + } + case LTTNG_RING_BUFFER_INSTANCE_ID: + { + uint64_t id; + + ret = ops->instance_id(config, buf, &id); + if (ret < 0) + goto error; + return put_u64(id, arg); + } default: return lib_ring_buffer_file_operations.unlocked_ioctl(filp, cmd, arg); @@ -1591,6 +1657,24 @@ static long lttng_stream_ring_buffer_compat_ioctl(struct file *filp, goto error; return put_u64(ts, arg); } + case LTTNG_RING_BUFFER_COMPAT_GET_SEQ_NUM: + { + uint64_t seq; + + ret = ops->sequence_number(config, buf, &seq); + if (ret < 0) + goto error; + return put_u64(seq, arg); + } + case LTTNG_RING_BUFFER_COMPAT_INSTANCE_ID: + { + uint64_t id; + + ret = ops->instance_id(config, buf, &id); + if (ret < 0) + goto error; + return put_u64(id, arg); + } default: return lib_ring_buffer_file_operations.compat_ioctl(filp, cmd, arg); @@ -1629,6 +1713,13 @@ int __init lttng_abi_init(void) int ret = 0; wrapper_vmalloc_sync_all(); + lttng_clock_ref(); + + ret = lttng_tp_mempool_init(); + if (ret) { + goto error; + } + lttng_proc_dentry = proc_create_data("lttng", S_IRUSR | S_IWUSR, NULL, <tng_fops, NULL); @@ -1638,14 +1729,19 @@ int __init lttng_abi_init(void) goto error; } lttng_stream_override_ring_buffer_fops(); + return 0; error: + lttng_tp_mempool_destroy(); + lttng_clock_unref(); return ret; } /* No __exit annotation because used by init error path too. */ void lttng_abi_exit(void) { + lttng_tp_mempool_destroy(); + lttng_clock_unref(); if (lttng_proc_dentry) remove_proc_entry("lttng", NULL); }