#include "wrapper/file.h"
#include <linux/jhash.h>
#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
#include "wrapper/uuid.h"
#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */
#include "lttng-events.h"
#include "lttng-tracer.h"
#include "lttng-abi-old.h"
+#include "wrapper/vzalloc.h"
#define METADATA_CACHE_DEFAULT_SIZE 4096
GFP_KERNEL);
if (!metadata_cache)
goto err_free_session;
- metadata_cache->data = kzalloc(METADATA_CACHE_DEFAULT_SIZE,
- GFP_KERNEL);
+ metadata_cache->data = lttng_vzalloc(METADATA_CACHE_DEFAULT_SIZE);
if (!metadata_cache->data)
goto err_free_cache;
metadata_cache->cache_alloc = METADATA_CACHE_DEFAULT_SIZE;
{
struct lttng_metadata_cache *cache =
container_of(kref, struct lttng_metadata_cache, refcount);
- kfree(cache->data);
+ vfree(cache->data);
kfree(cache);
}
ret = -EEXIST;
goto end;
}
- ACCESS_ONCE(event->enabled) = 1;
- lttng_session_sync_enablers(event->chan->session);
+ switch (event->instrumentation) {
+ case LTTNG_KERNEL_TRACEPOINT:
+ case LTTNG_KERNEL_SYSCALL:
+ ret = -EINVAL;
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ case LTTNG_KERNEL_FUNCTION:
+ case LTTNG_KERNEL_NOOP:
+ ACCESS_ONCE(event->enabled) = 1;
+ break;
+ case LTTNG_KERNEL_KRETPROBE:
+ ret = lttng_kretprobes_event_enable_state(event, 1);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ }
end:
mutex_unlock(&sessions_mutex);
return ret;
ret = -EEXIST;
goto end;
}
- ACCESS_ONCE(event->enabled) = 0;
- lttng_session_sync_enablers(event->chan->session);
+ switch (event->instrumentation) {
+ case LTTNG_KERNEL_TRACEPOINT:
+ case LTTNG_KERNEL_SYSCALL:
+ ret = -EINVAL;
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ case LTTNG_KERNEL_FUNCTION:
+ case LTTNG_KERNEL_NOOP:
+ ACCESS_ONCE(event->enabled) = 0;
+ break;
+ case LTTNG_KERNEL_KRETPROBE:
+ ret = lttng_kretprobes_event_enable_state(event, 0);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ }
end:
mutex_unlock(&sessions_mutex);
return ret;
smp_wmb();
break;
case LTTNG_KERNEL_KPROBE:
- event->enabled = 1;
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ event->enabled = 0;
event->registered = 1;
/*
* Populate lttng_event structure before event
struct lttng_event *event_return;
/* kretprobe defines 2 events */
- event->enabled = 1;
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ event->enabled = 0;
event->registered = 1;
event_return =
kmem_cache_zalloc(event_cache, GFP_KERNEL);
event_return->chan = chan;
event_return->filter = filter;
event_return->id = chan->free_event_id++;
- event_return->enabled = 1;
+ event_return->enabled = 0;
event_return->registered = 1;
event_return->instrumentation = itype;
/*
break;
}
case LTTNG_KERNEL_FUNCTION:
- event->enabled = 1;
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ event->enabled = 0;
event->registered = 1;
/*
* Populate lttng_event structure before event
break;
case LTTNG_KERNEL_NOOP:
case LTTNG_KERNEL_SYSCALL:
- event->enabled = 1;
+ /*
+ * Needs to be explicitly enabled after creation, since
+ * we may want to apply filters.
+ */
+ event->enabled = 0;
event->registered = 0;
event->desc = event_desc;
if (!event->desc) {
ret = PTR_ERR(tracker_pids_list_file);
goto file_error;
}
+ if (atomic_long_add_unless(&session->file->f_count,
+ 1, INT_MAX) == INT_MAX) {
+ goto refcount_error;
+ }
ret = lttng_tracker_pids_list_fops.open(NULL, tracker_pids_list_file);
if (ret < 0)
goto open_error;
m = tracker_pids_list_file->private_data;
m->private = session;
fd_install(file_fd, tracker_pids_list_file);
- atomic_long_inc(&session->file->f_count);
return file_fd;
open_error:
+ atomic_long_dec(&session->file->f_count);
+refcount_error:
fput(tracker_pids_list_file);
file_error:
put_unused_fd(file_fd);
tmp_cache_alloc_size = max_t(unsigned int,
session->metadata_cache->cache_alloc + len,
session->metadata_cache->cache_alloc << 1);
- tmp_cache_realloc = krealloc(session->metadata_cache->data,
- tmp_cache_alloc_size, GFP_KERNEL);
+ tmp_cache_realloc = lttng_vzalloc(tmp_cache_alloc_size);
if (!tmp_cache_realloc)
goto err;
+ if (session->metadata_cache->data) {
+ memcpy(tmp_cache_realloc,
+ session->metadata_cache->data,
+ session->metadata_cache->cache_alloc);
+ vfree(session->metadata_cache->data);
+ }
+
session->metadata_cache->cache_alloc = tmp_cache_alloc_size;
session->metadata_cache->data = tmp_cache_realloc;
}
* taken at start of trace.
* Yes, this is only an approximation. Yes, we can (and will) do better
* in future versions.
+ * Return 0 if offset is negative. It may happen if the system sets
+ * the REALTIME clock to 0 after boot.
*/
static
uint64_t measure_clock_offset(void)
{
- uint64_t offset, monotonic[2], realtime;
+ uint64_t monotonic_avg, monotonic[2], realtime;
+ int64_t offset;
struct timespec rts = { 0, 0 };
unsigned long flags;
monotonic[1] = trace_clock_read64();
local_irq_restore(flags);
- offset = (monotonic[0] + monotonic[1]) >> 1;
+ monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
realtime = (uint64_t) rts.tv_sec * NSEC_PER_SEC;
realtime += rts.tv_nsec;
- offset = realtime - offset;
+ offset = (int64_t) realtime - monotonic_avg;
+ if (offset < 0)
+ return 0;
return offset;
}