The liblttngkconsumerd can now be used to dump snapshots to tracefiles
for one or all buffers configured for mmap output.

Signed-off-by: Julien Desfossez <[email protected]>
---
 include/lttng/lttng-kconsumerd.h     |   29 +++++
 liblttngkconsumerd/lttngkconsumerd.c |  224 ++++++++++++++++++++++++----------
 2 files changed, 191 insertions(+), 62 deletions(-)

diff --git a/include/lttng/lttng-kconsumerd.h b/include/lttng/lttng-kconsumerd.h
index 8d16d56..454af6e 100644
--- a/include/lttng/lttng-kconsumerd.h
+++ b/include/lttng/lttng-kconsumerd.h
@@ -70,6 +70,7 @@ struct lttng_kconsumerd_fd {
        unsigned long max_sb_size; /* the subbuffer size for this channel */
        void *mmap_base;
        size_t mmap_len;
+       unsigned long snapshot_start;
        enum lttng_event_output output; /* splice or mmap */
 };
 
@@ -132,6 +133,34 @@ extern int lttng_kconsumerd_on_read_subbuffer_splice(
                struct lttng_kconsumerd_fd *kconsumerd_fd, unsigned long len);
 
 /*
+ * Capture a snapshot for all mmap buffers
+ *
+ * Returns 0 on success, < 0 on error
+ */
+extern int lttng_kconsumerd_get_all_snapshots(
+               struct lttng_kconsumerd_local_data *ctx);
+
+/*
+ * Capture a snapshot for a specific fd
+ * this function is responsible for reserving the subbuffer
+ * reading its content and releasing it.
+ *
+ * Returns 0 on success, < 0 on error
+ */
+extern int lttng_kconsumerd_get_snapshot(
+               struct lttng_kconsumerd_local_data *ctx,
+               struct lttng_kconsumerd_fd *kconsumerd_fd);
+
+/*
+ * Dump a snapshot to a tracefile
+ *
+ * Returns 0 on success, < 0 on error
+ */
+extern int lttng_kconsumerd_on_read_subbuffer_mmap_snapshot(
+               struct lttng_kconsumerd_local_data *ctx,
+               struct lttng_kconsumerd_fd *kconsumerd_fd, unsigned long end);
+
+/*
  * Send return code to session daemon.
  *
  * Returns the return code of sendmsg : the number of bytes transmitted or -1
diff --git a/liblttngkconsumerd/lttngkconsumerd.c 
b/liblttngkconsumerd/lttngkconsumerd.c
index ba26026..81749be 100644
--- a/liblttngkconsumerd/lttngkconsumerd.c
+++ b/liblttngkconsumerd/lttngkconsumerd.c
@@ -150,6 +150,7 @@ static int kconsumerd_add_fd(struct lttcomm_kconsumerd_msg 
*buf,
        tmp_fd->mmap_len = 0;
        tmp_fd->mmap_base = NULL;
        tmp_fd->output = buf->output;
+       tmp_fd->snapshot_start = 0;
        strncpy(tmp_fd->path_name, buf->path_name, PATH_MAX);
        tmp_fd->path_name[PATH_MAX - 1] = '\0';
 
@@ -361,6 +362,42 @@ void lttng_kconsumerd_set_command_sock_path(
        ctx->kconsumerd_command_sock_path = sock;
 }
 
+static void lttng_kconsumerd_sync_trace_file(
+               struct lttng_kconsumerd_fd *kconsumerd_fd, off_t orig_offset)
+{
+       int outfd = kconsumerd_fd->out_fd;
+       /*
+        * This does a blocking write-and-wait on any page that belongs to the
+        * subbuffer prior to the one we just wrote.
+        * Don't care about error values, as these are just hints and ways to
+        * limit the amount of page cache used.
+        */
+       if (orig_offset >= kconsumerd_fd->max_sb_size) {
+               sync_file_range(outfd, orig_offset - kconsumerd_fd->max_sb_size,
+                               kconsumerd_fd->max_sb_size,
+                               SYNC_FILE_RANGE_WAIT_BEFORE
+                               | SYNC_FILE_RANGE_WRITE
+                               | SYNC_FILE_RANGE_WAIT_AFTER);
+               /*
+                * Give hints to the kernel about how we access the file:
+                * POSIX_FADV_DONTNEED : we won't re-access data in a near 
future after
+                * we write it.
+                *
+                * We need to call fadvise again after the file grows because 
the
+                * kernel does not seem to apply fadvise to non-existing parts 
of the
+                * file.
+                *
+                * Call fadvise _after_ having waited for the page writeback to
+                * complete because the dirty page writeback semantic is not 
well
+                * defined. So it can be expected to lead to lower throughput in
+                * streaming.
+                */
+               posix_fadvise(outfd, orig_offset - kconsumerd_fd->max_sb_size,
+                               kconsumerd_fd->max_sb_size, 
POSIX_FADV_DONTNEED);
+       }
+}
+
+
 /*
  * Mmap the ring buffer, read it and write the data to the tracefile.
  *
@@ -371,7 +408,6 @@ int lttng_kconsumerd_on_read_subbuffer_mmap(
                struct lttng_kconsumerd_fd *kconsumerd_fd, unsigned long len)
 {
        unsigned long mmap_offset;
-       char *padding = NULL;
        long ret = 0;
        off_t orig_offset = kconsumerd_fd->out_fd_offset;
        int fd = kconsumerd_fd->consumerd_fd;
@@ -400,42 +436,11 @@ int lttng_kconsumerd_on_read_subbuffer_mmap(
                kconsumerd_fd->out_fd_offset += ret;
        }
 
-       /*
-        * This does a blocking write-and-wait on any page that belongs to the
-        * subbuffer prior to the one we just wrote.
-        * Don't care about error values, as these are just hints and ways to
-        * limit the amount of page cache used.
-        */
-       if (orig_offset >= kconsumerd_fd->max_sb_size) {
-               sync_file_range(outfd, orig_offset - kconsumerd_fd->max_sb_size,
-                               kconsumerd_fd->max_sb_size,
-                               SYNC_FILE_RANGE_WAIT_BEFORE
-                               | SYNC_FILE_RANGE_WRITE
-                               | SYNC_FILE_RANGE_WAIT_AFTER);
+       lttng_kconsumerd_sync_trace_file(kconsumerd_fd, orig_offset);
 
-               /*
-                * Give hints to the kernel about how we access the file:
-                * POSIX_FADV_DONTNEED : we won't re-access data in a near 
future after
-                * we write it.
-                *
-                * We need to call fadvise again after the file grows because 
the
-                * kernel does not seem to apply fadvise to non-existing parts 
of the
-                * file.
-                *
-                * Call fadvise _after_ having waited for the page writeback to
-                * complete because the dirty page writeback semantic is not 
well
-                * defined. So it can be expected to lead to lower throughput in
-                * streaming.
-                */
-               posix_fadvise(outfd, orig_offset - kconsumerd_fd->max_sb_size,
-                               kconsumerd_fd->max_sb_size, 
POSIX_FADV_DONTNEED);
-       }
        goto end;
 
 end:
-       if (padding != NULL) {
-               free(padding);
-       }
        return ret;
 }
 
@@ -482,36 +487,8 @@ int lttng_kconsumerd_on_read_subbuffer_splice(
                                SYNC_FILE_RANGE_WRITE);
                kconsumerd_fd->out_fd_offset += ret;
        }
+       lttng_kconsumerd_sync_trace_file(kconsumerd_fd, orig_offset);
 
-       /*
-        * This does a blocking write-and-wait on any page that belongs to the
-        * subbuffer prior to the one we just wrote.
-        * Don't care about error values, as these are just hints and ways to
-        * limit the amount of page cache used.
-        */
-       if (orig_offset >= kconsumerd_fd->max_sb_size) {
-               sync_file_range(outfd, orig_offset - kconsumerd_fd->max_sb_size,
-                               kconsumerd_fd->max_sb_size,
-                               SYNC_FILE_RANGE_WAIT_BEFORE
-                               | SYNC_FILE_RANGE_WRITE
-                               | SYNC_FILE_RANGE_WAIT_AFTER);
-               /*
-                * Give hints to the kernel about how we access the file:
-                * POSIX_FADV_DONTNEED : we won't re-access data in a near 
future after
-                * we write it.
-                *
-                * We need to call fadvise again after the file grows because 
the
-                * kernel does not seem to apply fadvise to non-existing parts 
of the
-                * file.
-                *
-                * Call fadvise _after_ having waited for the page writeback to
-                * complete because the dirty page writeback semantic is not 
well
-                * defined. So it can be expected to lead to lower throughput in
-                * streaming.
-                */
-               posix_fadvise(outfd, orig_offset - kconsumerd_fd->max_sb_size,
-                               kconsumerd_fd->max_sb_size, 
POSIX_FADV_DONTNEED);
-       }
        goto end;
 
 splice_error:
@@ -536,6 +513,129 @@ end:
 }
 
 /*
+ * Capture a snapshot for all mmap buffers
+ *
+ * Returns 0 on success, < 0 on error
+ */
+int lttng_kconsumerd_get_all_snapshots(struct lttng_kconsumerd_local_data *ctx)
+{
+       struct lttng_kconsumerd_fd *iter, *tmp;
+       int ret = 0;
+
+       pthread_mutex_lock(&kconsumerd_data.lock);
+       cds_list_for_each_entry_safe(iter, tmp, &kconsumerd_data.fd_list.head, 
list) {
+               if (iter->output == LTTNG_EVENT_MMAP) {
+                       ret = lttng_kconsumerd_get_snapshot(ctx, iter);
+                       if (ret < 0) {
+                               goto end;
+                       }
+               }
+       }
+       pthread_mutex_unlock(&kconsumerd_data.lock);
+
+end:
+       return ret;
+}
+
+/*
+ * Capture a snapshot for a specific fd
+ * this function is responsible for reserving the subbuffer
+ * reading its content and releasing it.
+ *
+ * Returns 0 on success, < 0 on error
+ */
+int lttng_kconsumerd_get_snapshot(struct lttng_kconsumerd_local_data *ctx,
+               struct lttng_kconsumerd_fd *kconsumerd_fd)
+{
+       unsigned long len;
+       int err;
+       long ret = 0;
+       int infd = kconsumerd_fd->consumerd_fd;
+
+       err = kernctl_snapshot(infd);
+       if (err != 0) {
+               ret = errno;
+               perror("Getting sub-buffer snapshot.");
+               goto end;
+       }
+       err = kernctl_snapshot_get_produced(infd, &len);
+       if (err != 0) {
+               ret = errno;
+               perror("kernctl_snapshot_get_produced");
+               goto end;
+       }
+       /* write the subbuffer to the tracefile */
+       ret = lttng_kconsumerd_on_read_subbuffer_mmap_snapshot(ctx,
+                       kconsumerd_fd, len);
+       if (ret < 0) {
+               ERR("Error writing to tracefile");
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Dump a snapshot to a tracefile
+ *
+ * Returns 0 on success, < 0 on error
+ */
+int lttng_kconsumerd_on_read_subbuffer_mmap_snapshot(
+               struct lttng_kconsumerd_local_data *ctx,
+               struct lttng_kconsumerd_fd *kconsumerd_fd, unsigned long end)
+{
+       unsigned long len;
+       long ret = 0;
+       off_t orig_offset = kconsumerd_fd->out_fd_offset;
+       int fd = kconsumerd_fd->consumerd_fd;
+       int outfd = kconsumerd_fd->out_fd;
+       unsigned long start = kconsumerd_fd->snapshot_start;
+       unsigned long max_subbuf_size = kconsumerd_fd->max_sb_size;
+
+       len = end - start;
+       DBG("snapshot len = %lu, need to read %lu subbuff\n", len,
+                       len/max_subbuf_size);
+       while (len > 0) {
+               DBG("reading snapshot at pos %lu on fd %d\n", start, fd);
+               ret = kernctl_get_subbuf(fd, &start);
+               if (ret != 0) {
+                       ret = errno;
+                       perror("kernctl_get_subbuf");
+                       goto end;
+               }
+
+               ret = write(outfd, kconsumerd_fd->mmap_base + start, 
max_subbuf_size);
+               if (ret >= max_subbuf_size) {
+                       len -= max_subbuf_size;
+               } else if (ret < 0) {
+                       ret = errno;
+                       perror("Error in file write");
+                       goto end;
+               }
+               ret = kernctl_put_next_subbuf(fd);
+               if (ret != 0) {
+                       ret = errno;
+                       perror("kernctl_put_subbuf");
+                       goto end;
+               }
+
+               start += max_subbuf_size;
+               kconsumerd_fd->snapshot_start += max_subbuf_size;
+               if (outfd != 0) {
+                       /* This won't block, but will start writeout 
asynchronously */
+                       sync_file_range(outfd, kconsumerd_fd->out_fd_offset, 
ret,
+                                       SYNC_FILE_RANGE_WRITE);
+                       kconsumerd_fd->out_fd_offset += ret;
+               }
+       }
+
+       lttng_kconsumerd_sync_trace_file(kconsumerd_fd, orig_offset);
+
+end:
+       return ret;
+}
+
+/*
  * Poll on the should_quit pipe and the command socket return -1 on error and
  * should exit, 0 if data is available on the command socket
  */
-- 
1.7.4.1


_______________________________________________
ltt-dev mailing list
[email protected]
http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev

Reply via email to