Implement file-backed ring buffer
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 8 Jul 2014 14:11:09 +0000 (10:11 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 26 Mar 2015 21:38:11 +0000 (17:38 -0400)
Allow using the --shm-path option in LTTng to specify the location of
the files backing the UST ring buffer. Useful for trace extraction upon
crash, especially by using a persistent memory filesystem as storage for
the files.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 files changed:
include/lttng/ringbuffer-config.h
include/lttng/ust-ctl.h
include/lttng/ust-events.h
liblttng-ust-ctl/ustctl.c
liblttng-ust/lttng-ring-buffer-client.h
liblttng-ust/lttng-ring-buffer-metadata-client.h
libringbuffer/backend_internal.h
libringbuffer/frontend.h
libringbuffer/frontend_types.h
libringbuffer/ring_buffer_backend.c
libringbuffer/ring_buffer_frontend.c
libringbuffer/shm.c
libringbuffer/shm.h
libringbuffer/shm_types.h

index 9de9a73807ca634e4795bf70e39e44e5e0f9bf11..87344c94c8285f94b296f318ae58880dedcc7a39 100644 (file)
@@ -92,6 +92,13 @@ struct lttng_ust_lib_ring_buffer_client_cb {
                            size_t offset, size_t *header_len,
                            size_t *payload_len, uint64_t *timestamp,
                            struct lttng_ust_shm_handle *handle);
+       /*
+        * Offset and size of content size field in client.
+        */
+       void (*content_size_field) (const struct lttng_ust_lib_ring_buffer_config *config,
+                               size_t *offset, size_t *length);
+       void (*packet_size_field) (const struct lttng_ust_lib_ring_buffer_config *config,
+                               size_t *offset, size_t *length);
 };
 
 /*
@@ -146,8 +153,8 @@ enum lttng_ust_lib_ring_buffer_sync_types {
 };
 
 enum lttng_ust_lib_ring_buffer_mode_types {
-       RING_BUFFER_OVERWRITE,          /* Overwrite when buffer full */
-       RING_BUFFER_DISCARD,            /* Discard when buffer full */
+       RING_BUFFER_OVERWRITE = 0,      /* Overwrite when buffer full */
+       RING_BUFFER_DISCARD = 1,        /* Discard when buffer full */
 };
 
 enum lttng_ust_lib_ring_buffer_output_types {
index 8e60f0d8e4db572c4b7c4f32f7ed50534a241c8c..0add179192c9e265173d80c80e75f0f4c5176e31 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <lttng/ust-abi.h>
 #include <sys/types.h>
+#include <limits.h>
 
 #ifndef LTTNG_UST_UUID_LEN
 #define LTTNG_UST_UUID_LEN     16
@@ -52,6 +53,7 @@ struct ustctl_consumer_channel_attr {
        enum lttng_ust_output output;           /* splice, mmap */
        uint32_t chan_id;                       /* channel ID */
        unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */
+       char shm_path[PATH_MAX];                /* Shared memory path */
 } LTTNG_PACKED;
 
 /*
index 9a46e678ad782afaaf13a3b97df3a0adf1ed5f89..e4b4edeba005e25e926a54a7674d51915e766d65 100644 (file)
@@ -439,7 +439,8 @@ struct lttng_channel_ops {
                        unsigned int switch_timer_interval,
                        unsigned int read_timer_interval,
                        unsigned char *uuid,
-                       uint32_t chan_id);
+                       uint32_t chan_id,
+                       const char *shm_path);
        void (*channel_destroy)(struct lttng_channel *chan);
        union {
                void *_deprecated1;
index 3554d13f4db59506275209d5294cfd0cf85ddd74..aaad99acf1bf5a87b68a50bd7508c08cb5ca6cf9 100644 (file)
@@ -995,7 +995,8 @@ struct ustctl_consumer_channel *
                        attr->subbuf_size, attr->num_subbuf,
                        attr->switch_timer_interval,
                        attr->read_timer_interval,
-                       attr->uuid, attr->chan_id);
+                       attr->uuid, attr->chan_id,
+                       attr->shm_path[0] == '\0' ? NULL : attr->shm_path);
        if (!chan->chan) {
                goto chan_error;
        }
index 96aeb1e5d7d2b5c5116ae884e9481e8e6b7370cd..79085e57a55e7dd73e4fa71b01c4b2aa21bd5142 100644 (file)
@@ -388,6 +388,20 @@ static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, void *
 {
 }
 
+static void client_content_size_field(const struct lttng_ust_lib_ring_buffer_config *config,
+                                     size_t *offset, size_t *length)
+{
+       *offset = offsetof(struct packet_header, ctx.content_size);
+       *length = sizeof(((struct packet_header *) NULL)->ctx.content_size);
+}
+
+static void client_packet_size_field(const struct lttng_ust_lib_ring_buffer_config *config,
+                                     size_t *offset, size_t *length)
+{
+       *offset = offsetof(struct packet_header, ctx.packet_size);
+       *length = sizeof(((struct packet_header *) NULL)->ctx.packet_size);
+}
+
 static struct packet_header *client_packet_header(struct lttng_ust_lib_ring_buffer *buf,
                struct lttng_ust_shm_handle *handle)
 {
@@ -482,6 +496,8 @@ struct lttng_ust_client_lib_ring_buffer_client_cb client_cb = {
                .buffer_end = client_buffer_end,
                .buffer_create = client_buffer_create,
                .buffer_finalize = client_buffer_finalize,
+               .content_size_field = client_content_size_field,
+               .packet_size_field = client_packet_size_field,
        },
        .timestamp_begin = client_timestamp_begin,
        .timestamp_end = client_timestamp_end,
@@ -500,6 +516,8 @@ static const struct lttng_ust_lib_ring_buffer_config client_config = {
        .cb.buffer_end = client_buffer_end,
        .cb.buffer_create = client_buffer_create,
        .cb.buffer_finalize = client_buffer_finalize,
+       .cb.content_size_field = client_content_size_field,
+       .cb.packet_size_field = client_packet_size_field,
 
        .tsc_bits = LTTNG_COMPACT_TSC_BITS,
        .alloc = RING_BUFFER_ALLOC_PER_CPU,
@@ -524,7 +542,8 @@ struct lttng_channel *_channel_create(const char *name,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
                                unsigned char *uuid,
-                               uint32_t chan_id)
+                               uint32_t chan_id,
+                               const char *shm_path)
 {
        struct lttng_channel chan_priv_init;
        struct lttng_ust_shm_handle *handle;
@@ -539,7 +558,8 @@ struct lttng_channel *_channel_create(const char *name,
                        sizeof(struct lttng_channel),
                        &chan_priv_init,
                        buf_addr, subbuf_size, num_subbuf,
-                       switch_timer_interval, read_timer_interval);
+                       switch_timer_interval, read_timer_interval,
+                       shm_path);
        if (!handle)
                return NULL;
        lttng_chan = priv;
index 0d2a1f838e623ab8147221f23ed4e9ad3a487720..8d725f2a8e1e7622a854a8a4867f031e99aaf55f 100644 (file)
@@ -199,7 +199,8 @@ struct lttng_channel *_channel_create(const char *name,
                                unsigned int switch_timer_interval,
                                unsigned int read_timer_interval,
                                unsigned char *uuid,
-                               uint32_t chan_id)
+                               uint32_t chan_id,
+                               const char *shm_path)
 {
        struct lttng_channel chan_priv_init;
        struct lttng_ust_shm_handle *handle;
@@ -214,7 +215,8 @@ struct lttng_channel *_channel_create(const char *name,
                        sizeof(struct lttng_channel),
                        &chan_priv_init,
                        buf_addr, subbuf_size, num_subbuf,
-                       switch_timer_interval, read_timer_interval);
+                       switch_timer_interval, read_timer_interval,
+                       shm_path);
        if (!handle)
                return NULL;
        lttng_chan = priv;
index 1045a60c2760ae2314f4d0ab89a7aedcebabf387..3c09382ed117b262f5f4baf275043271f069359d 100644 (file)
@@ -45,7 +45,8 @@ int channel_backend_init(struct channel_backend *chanb,
                         const char *name,
                         const struct lttng_ust_lib_ring_buffer_config *config,
                         size_t subbuf_size,
-                        size_t num_subbuf, struct lttng_ust_shm_handle *handle);
+                        size_t num_subbuf, struct lttng_ust_shm_handle *handle,
+                        const char *shm_path);
 void channel_backend_free(struct channel_backend *chanb,
                          struct lttng_ust_shm_handle *handle);
 
index 89613d4cc64823a943ad3f42d17be83e0140d3c9..770090770e9de16081a351db63f571616c4627b3 100644 (file)
@@ -64,7 +64,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
                                void *buf_addr,
                                size_t subbuf_size, size_t num_subbuf,
                                unsigned int switch_timer_interval,
-                               unsigned int read_timer_interval);
+                               unsigned int read_timer_interval,
+                               const char *shm_path);
 
 /*
  * channel_destroy finalizes all channel's buffers, waits for readers to
index b44783f713630a584e99e28bd6c6982f5bf08444..bf4b4185e2368945494dd39e3df86efed5ff1aa8 100644 (file)
@@ -94,10 +94,90 @@ struct commit_counters_cold {
 } __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
 
 /* ring buffer state */
-#define RB_RING_BUFFER_PADDING         64
+#define RB_CRASH_DUMP_ABI_LEN          256
+#define RB_RING_BUFFER_PADDING         60
+
+#define RB_CRASH_DUMP_ABI_MAGIC_LEN    16
+
+/*
+ * The 128-bit magic number is xor'd in the process data so it does not
+ * cause a false positive when searching for buffers by scanning memory.
+ * The actual magic number is:
+ *   0x17, 0x7B, 0xF1, 0x77, 0xBF, 0x17, 0x7B, 0xF1,
+ *   0x77, 0xBF, 0x17, 0x7B, 0xF1, 0x77, 0xBF, 0x17,
+ */
+#define RB_CRASH_DUMP_ABI_MAGIC_XOR                                    \
+       {                                                               \
+               0x17 ^ 0xFF, 0x7B ^ 0xFF, 0xF1 ^ 0xFF, 0x77 ^ 0xFF,     \
+               0xBF ^ 0xFF, 0x17 ^ 0xFF, 0x7B ^ 0xFF, 0xF1 ^ 0xFF,     \
+               0x77 ^ 0xFF, 0xBF ^ 0xFF, 0x17 ^ 0xFF, 0x7B ^ 0xFF,     \
+               0xF1 ^ 0xFF, 0x77 ^ 0xFF, 0xBF ^ 0xFF, 0x17 ^ 0xFF,     \
+       }
+
+#define RB_CRASH_ENDIAN                        0x1234
+
+#define RB_CRASH_DUMP_ABI_MAJOR                0
+#define RB_CRASH_DUMP_ABI_MINOR                0
+
+enum lttng_crash_type {
+       LTTNG_CRASH_TYPE_UST = 0,
+       LTTNG_CRASH_TYPE_KERNEL = 1,
+};
+
+struct lttng_crash_abi {
+       uint8_t magic[RB_CRASH_DUMP_ABI_MAGIC_LEN];
+       uint64_t mmap_length;   /* Overall lenght of crash record */
+       uint16_t endian;        /*
+                                * { 0x12, 0x34 }: big endian
+                                * { 0x34, 0x12 }: little endian
+                                */
+       uint16_t major;         /* Major number. */
+       uint16_t minor;         /* Minor number. */
+       uint8_t word_size;      /* Word size (bytes). */
+       uint8_t layout_type;    /* enum lttng_crash_type */
+
+       struct {
+               uint32_t prod_offset;
+               uint32_t consumed_offset;
+               uint32_t commit_hot_array;
+               uint32_t commit_hot_seq;
+               uint32_t buf_wsb_array;
+               uint32_t buf_wsb_id;
+               uint32_t sb_array;
+               uint32_t sb_array_shmp_offset;
+               uint32_t sb_backend_p_offset;
+               uint32_t content_size;
+               uint32_t packet_size;
+       } __attribute__((packed)) offset;
+       struct {
+               uint8_t prod_offset;
+               uint8_t consumed_offset;
+               uint8_t commit_hot_seq;
+               uint8_t buf_wsb_id;
+               uint8_t sb_array_shmp_offset;
+               uint8_t sb_backend_p_offset;
+               uint8_t content_size;
+               uint8_t packet_size;
+       } __attribute__((packed)) length;
+       struct {
+               uint32_t commit_hot_array;
+               uint32_t buf_wsb_array;
+               uint32_t sb_array;
+       } __attribute__((packed)) stride;
+
+       uint64_t buf_size;      /* Size of the buffer */
+       uint64_t subbuf_size;   /* Sub-buffer size */
+       uint64_t num_subbuf;    /* Number of sub-buffers for writer */
+       uint32_t mode;          /* Buffer mode: 0: overwrite, 1: discard */
+} __attribute__((packed));
+
 struct lttng_ust_lib_ring_buffer {
-       /* First 32 bytes cache-hot cacheline */
-       union v_atomic offset;          /* Current offset in the buffer */
+       /* First 32 bytes are for the buffer crash dump ABI */
+       struct lttng_crash_abi crash_abi;
+
+       /* 32 bytes cache-hot cacheline */
+       union v_atomic __attribute__((aligned(32))) offset;
+                                       /* Current offset in the buffer */
        DECLARE_SHMP(struct commit_counters_hot, commit_hot);
                                        /* Commit count per sub-buffer */
        long consumed;                  /*
@@ -105,12 +185,14 @@ struct lttng_ust_lib_ring_buffer {
                                         * standard atomic access (shared)
                                         */
        int record_disabled;
-       /* End of first 32 bytes cacheline */
+       /* End of cache-hot 32 bytes cacheline */
+
        union v_atomic last_tsc;        /*
                                         * Last timestamp written in the buffer.
                                         */
 
-       struct lttng_ust_lib_ring_buffer_backend backend;       /* Associated backend */
+       struct lttng_ust_lib_ring_buffer_backend backend;
+                                       /* Associated backend */
 
        DECLARE_SHMP(struct commit_counters_cold, commit_cold);
                                        /* Commit count per sub-buffer */
index 7d3a37809e73da27b25d43d8914ed285545075f7..3a667adce53c8ccdda4f15b872c13d054907f7ed 100644 (file)
@@ -29,6 +29,8 @@
 #include "smp.h"
 #include "shm.h"
 
+#define UINT_MAX_STR_LEN 11    /* includes \0 */
+
 /**
  * lib_ring_buffer_backend_allocate - allocate a channel buffer
  * @config: ring buffer instance configuration
@@ -115,7 +117,6 @@ int lib_ring_buffer_backend_allocate(const struct lttng_ust_lib_ring_buffer_conf
                        mmap_offset += subbuf_size;
                }
        }
-
        return 0;
 
 free_array:
@@ -199,6 +200,7 @@ void channel_backend_reset(struct channel_backend *chanb)
  * @subbuf_size: size of sub-buffers (> PAGE_SIZE, power of 2)
  * @num_subbuf: number of sub-buffers (power of 2)
  * @lttng_ust_shm_handle: shared memory handle
+ * @shm_path: shared memory files path
  *
  * Returns channel pointer if successful, %NULL otherwise.
  *
@@ -212,7 +214,8 @@ int channel_backend_init(struct channel_backend *chanb,
                         const char *name,
                         const struct lttng_ust_lib_ring_buffer_config *config,
                         size_t subbuf_size, size_t num_subbuf,
-                        struct lttng_ust_shm_handle *handle)
+                        struct lttng_ust_shm_handle *handle,
+                        const char *shm_path)
 {
        struct channel *chan = caa_container_of(chanb, struct channel, backend);
        unsigned int i;
@@ -285,9 +288,21 @@ int channel_backend_init(struct channel_backend *chanb,
                 */
                for_each_possible_cpu(i) {
                        struct shm_object *shmobj;
-
+                       char shm_buf_path[PATH_MAX];
+
+                       if (shm_path) {
+                               char cpu_nr[UINT_MAX_STR_LEN];  /* unsigned int max len */
+
+                               strncpy(shm_buf_path, shm_path, PATH_MAX);
+                               shm_buf_path[PATH_MAX - 1] = '\0';
+                               ret = snprintf(cpu_nr, UINT_MAX_STR_LEN, "%u", i);
+                               if (ret != 1)
+                                       goto end;
+                               strncat(shm_buf_path, cpu_nr,
+                                       PATH_MAX - strlen(shm_buf_path) - 1);
+                       }
                        shmobj = shm_object_table_alloc(handle->table, shmsize,
-                                       SHM_OBJECT_SHM);
+                                       SHM_OBJECT_SHM, shm_path ? shm_buf_path : NULL);
                        if (!shmobj)
                                goto end;
                        align_shm(shmobj, __alignof__(struct lttng_ust_lib_ring_buffer));
@@ -306,7 +321,7 @@ int channel_backend_init(struct channel_backend *chanb,
                struct lttng_ust_lib_ring_buffer *buf;
 
                shmobj = shm_object_table_alloc(handle->table, shmsize,
-                                       SHM_OBJECT_SHM);
+                                       SHM_OBJECT_SHM, shm_path);
                if (!shmobj)
                        goto end;
                align_shm(shmobj, __alignof__(struct lttng_ust_lib_ring_buffer));
index aeb7f7d94a10a9c4b63d098df1191ba4cdcef47e..3cba68d4e7ef354b9d9ddd842378459fa975a4d1 100644 (file)
 #define LTTNG_UST_RING_BUFFER_GET_RETRY                10
 #define LTTNG_UST_RING_BUFFER_RETRY_DELAY_MS   10
 
+/*
+ * Non-static to ensure the compiler does not optimize away the xor.
+ */
+uint8_t lttng_crash_magic_xor[] = RB_CRASH_DUMP_ABI_MAGIC_XOR;
+
 /*
  * Use POSIX SHM: shm_open(3) and shm_unlink(3).
  * close(2) to close the fd returned by shm_open.
@@ -208,6 +213,95 @@ void channel_reset(struct channel *chan)
        /* Don't reset reader reference count */
 }
 
+static
+void init_crash_abi(const struct lttng_ust_lib_ring_buffer_config *config,
+               struct lttng_crash_abi *crash_abi,
+               struct lttng_ust_lib_ring_buffer *buf,
+               struct channel_backend *chanb,
+               struct shm_object *shmobj,
+               struct lttng_ust_shm_handle *handle)
+{
+       int i;
+
+       for (i = 0; i < RB_CRASH_DUMP_ABI_MAGIC_LEN; i++)
+               crash_abi->magic[i] = lttng_crash_magic_xor[i] ^ 0xFF;
+       crash_abi->mmap_length = shmobj->memory_map_size;
+       crash_abi->endian = RB_CRASH_ENDIAN;
+       crash_abi->major = RB_CRASH_DUMP_ABI_MAJOR;
+       crash_abi->minor = RB_CRASH_DUMP_ABI_MINOR;
+       crash_abi->word_size = sizeof(unsigned long);
+       crash_abi->layout_type = LTTNG_CRASH_TYPE_UST;
+
+       /* Offset of fields */
+       crash_abi->offset.prod_offset =
+               (uint32_t) ((char *) &buf->offset - (char *) buf);
+       crash_abi->offset.consumed_offset =
+               (uint32_t) ((char *) &buf->consumed - (char *) buf);
+       crash_abi->offset.commit_hot_array =
+               (uint32_t) ((char *) shmp(handle, buf->commit_hot) - (char *) buf);
+       crash_abi->offset.commit_hot_seq =
+               offsetof(struct commit_counters_hot, seq);
+       crash_abi->offset.buf_wsb_array =
+               (uint32_t) ((char *) shmp(handle, buf->backend.buf_wsb) - (char *) buf);
+       crash_abi->offset.buf_wsb_id =
+               offsetof(struct lttng_ust_lib_ring_buffer_backend_subbuffer, id);
+       crash_abi->offset.sb_array =
+               (uint32_t) ((char *) shmp(handle, buf->backend.array) - (char *) buf);
+       crash_abi->offset.sb_array_shmp_offset =
+               offsetof(struct lttng_ust_lib_ring_buffer_backend_pages_shmp,
+                       shmp._ref.offset);
+       crash_abi->offset.sb_backend_p_offset =
+               offsetof(struct lttng_ust_lib_ring_buffer_backend_pages,
+                       p._ref.offset);
+
+       /* Field length */
+       crash_abi->length.prod_offset = sizeof(buf->offset);
+       crash_abi->length.consumed_offset = sizeof(buf->consumed);
+       crash_abi->length.commit_hot_seq =
+               sizeof(((struct commit_counters_hot *) NULL)->seq);
+       crash_abi->length.buf_wsb_id =
+               sizeof(((struct lttng_ust_lib_ring_buffer_backend_subbuffer *) NULL)->id);
+       crash_abi->length.sb_array_shmp_offset =
+               sizeof(((struct lttng_ust_lib_ring_buffer_backend_pages_shmp *) NULL)->shmp._ref.offset);
+       crash_abi->length.sb_backend_p_offset =
+               sizeof(((struct lttng_ust_lib_ring_buffer_backend_pages *) NULL)->p._ref.offset);
+
+       /* Array stride */
+       crash_abi->stride.commit_hot_array =
+               sizeof(struct commit_counters_hot);
+       crash_abi->stride.buf_wsb_array =
+               sizeof(struct lttng_ust_lib_ring_buffer_backend_subbuffer);
+       crash_abi->stride.sb_array =
+               sizeof(struct lttng_ust_lib_ring_buffer_backend_pages_shmp);
+
+       /* Buffer constants */
+       crash_abi->buf_size = chanb->buf_size;
+       crash_abi->subbuf_size = chanb->subbuf_size;
+       crash_abi->num_subbuf = chanb->num_subbuf;
+       crash_abi->mode = (uint32_t) chanb->config.mode;
+
+       if (config->cb.content_size_field) {
+               size_t offset, length;
+
+               config->cb.content_size_field(config, &offset, &length);
+               crash_abi->offset.content_size = offset;
+               crash_abi->length.content_size = length;
+       } else {
+               crash_abi->offset.content_size = 0;
+               crash_abi->length.content_size = 0;
+       }
+       if (config->cb.packet_size_field) {
+               size_t offset, length;
+
+               config->cb.packet_size_field(config, &offset, &length);
+               crash_abi->offset.packet_size = offset;
+               crash_abi->length.packet_size = length;
+       } else {
+               crash_abi->offset.packet_size = 0;
+               crash_abi->length.packet_size = 0;
+       }
+}
+
 /*
  * Must be called under cpu hotplug protection.
  */
@@ -227,18 +321,12 @@ int lib_ring_buffer_create(struct lttng_ust_lib_ring_buffer *buf,
        if (buf->backend.allocated)
                return 0;
 
-       ret = lib_ring_buffer_backend_create(&buf->backend, &chan->backend,
-                       cpu, handle, shmobj);
-       if (ret)
-               return ret;
-
        align_shm(shmobj, __alignof__(struct commit_counters_hot));
        set_shmp(buf->commit_hot,
                 zalloc_shm(shmobj,
                        sizeof(struct commit_counters_hot) * chan->backend.num_subbuf));
        if (!shmp(handle, buf->commit_hot)) {
-               ret = -ENOMEM;
-               goto free_chanbuf;
+               return -ENOMEM;
        }
 
        align_shm(shmobj, __alignof__(struct commit_counters_cold));
@@ -250,6 +338,12 @@ int lib_ring_buffer_create(struct lttng_ust_lib_ring_buffer *buf,
                goto free_commit;
        }
 
+       ret = lib_ring_buffer_backend_create(&buf->backend, &chan->backend,
+                       cpu, handle, shmobj);
+       if (ret) {
+               goto free_init;
+       }
+
        /*
         * Write the subbuffer header for first subbuffer so we know the total
         * duration of data gathering.
@@ -260,12 +354,16 @@ int lib_ring_buffer_create(struct lttng_ust_lib_ring_buffer *buf,
        tsc = config->cb.ring_buffer_clock_read(shmp(handle, buf->backend.chan));
        config->cb.buffer_begin(buf, tsc, 0, handle);
        v_add(config, subbuf_header_size, &shmp_index(handle, buf->commit_hot, 0)->cc);
+       v_add(config, subbuf_header_size, &shmp_index(handle, buf->commit_hot, 0)->seq);
 
        if (config->cb.buffer_create) {
                ret = config->cb.buffer_create(buf, priv, cpu, chanb->name, handle);
                if (ret)
-                       goto free_init;
+                       goto free_chanbuf;
        }
+
+       init_crash_abi(config, &buf->crash_abi, buf, chanb, shmobj, handle);
+
        buf->backend.allocated = 1;
        return 0;
 
@@ -675,6 +773,7 @@ static void channel_free(struct channel *chan,
  *                         padding to let readers get those sub-buffers.
  *                         Used for live streaming.
  * @read_timer_interval: Time interval (in us) to wake up pending readers.
+ * @shm_path: Shared memory files path.
  *
  * Holds cpu hotplug.
  * Returns NULL on failure.
@@ -687,7 +786,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
                   void *priv_data_init,
                   void *buf_addr, size_t subbuf_size,
                   size_t num_subbuf, unsigned int switch_timer_interval,
-                  unsigned int read_timer_interval)
+                  unsigned int read_timer_interval,
+                  const char *shm_path)
 {
        int ret;
        size_t shmsize, chansize;
@@ -724,7 +824,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
        shmsize += priv_data_size;
 
        /* Allocate normal memory for channel (not shared) */
-       shmobj = shm_object_table_alloc(handle->table, shmsize, SHM_OBJECT_MEM);
+       shmobj = shm_object_table_alloc(handle->table, shmsize, SHM_OBJECT_MEM,
+                       NULL);
        if (!shmobj)
                goto error_append;
        /* struct channel is at object 0, offset 0 (hardcoded) */
@@ -754,7 +855,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff
        }
 
        ret = channel_backend_init(&chan->backend, name, config,
-                                  subbuf_size, num_subbuf, handle);
+                                  subbuf_size, num_subbuf, handle,
+                                  shm_path);
        if (ret)
                goto error_backend_init;
 
index 3bf648d253bd4f00ad8791b34cecb3d75e0c19d2..fb2df13bc11a5a1a43c0b5dc3394930fb8e1bd9a 100644 (file)
@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/types.h>
 #include <sys/stat.h>  /* For mode constants */
 #include <fcntl.h>     /* For O_* constants */
 #include <assert.h>
@@ -29,7 +30,6 @@
 #include <signal.h>
 #include <dirent.h>
 #include <lttng/align.h>
-#include <helper.h>
 #include <limits.h>
 #include <helper.h>
 
@@ -83,14 +83,69 @@ struct shm_object_table *shm_object_table_create(size_t max_nb_obj)
        return table;
 }
 
+static
+int create_posix_shm(void)
+{
+       char tmp_name[NAME_MAX] = "/ust-shm-tmp-XXXXXX";
+       int shmfd, ret;
+
+       /*
+        * Allocate shm, and immediately unlink its shm oject, keeping
+        * only the file descriptor as a reference to the object. If it
+        * already exists (caused by short race window during which the
+        * global object exists in a concurrent shm_open), simply retry.
+        * We specifically do _not_ use the / at the beginning of the
+        * pathname so that some OS implementations can keep it local to
+        * the process (POSIX leaves this implementation-defined).
+        */
+       do {
+               /*
+                * Using mktemp filename with O_CREAT | O_EXCL open
+                * flags.
+                */
+               (void) mktemp(tmp_name);
+               if (tmp_name[0] == '\0') {
+                       PERROR("mktemp");
+                       goto error_shm_open;
+               }
+               shmfd = shm_open(tmp_name,
+                                O_CREAT | O_EXCL | O_RDWR, 0700);
+       } while (shmfd < 0 && (errno == EEXIST || errno == EACCES));
+       if (shmfd < 0) {
+               PERROR("shm_open");
+               goto error_shm_open;
+       }
+       ret = shm_unlink(tmp_name);
+       if (ret < 0 && errno != ENOENT) {
+               PERROR("shm_unlink");
+               goto error_shm_release;
+       }
+       return shmfd;
+
+error_shm_release:
+       ret = close(shmfd);
+       if (ret) {
+               PERROR("close");
+               assert(0);
+       }
+error_shm_open:
+       return -1;
+}
+
+static
+int create_shared_file(const char *shm_path)
+{
+       return open(shm_path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+}
+
 static
 struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table,
-                                          size_t memory_map_size)
+                                          size_t memory_map_size,
+                                          const char *shm_path)
 {
        int shmfd, waitfd[2], ret, i, sigblocked = 0;
        struct shm_object *obj;
        char *memory_map;
-       char tmp_name[NAME_MAX] = "/ust-shm-tmp-XXXXXX";
        sigset_t all_sigs, orig_sigs;
 
        if (table->allocated_len >= table->size)
@@ -133,37 +188,21 @@ struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table,
        }
        sigblocked = 1;
 
-       /*
-        * Allocate shm, and immediately unlink its shm oject, keeping
-        * only the file descriptor as a reference to the object. If it
-        * already exists (caused by short race window during which the
-        * global object exists in a concurrent shm_open), simply retry.
-        * We specifically do _not_ use the / at the beginning of the
-        * pathname so that some OS implementations can keep it local to
-        * the process (POSIX leaves this implementation-defined).
-        */
-       do {
-               /*
-                * Using mktemp filename with O_CREAT | O_EXCL open
-                * flags.
-                */
-               (void) mktemp(tmp_name);
-               if (tmp_name[0] == '\0') {
-                       PERROR("mktemp");
-                       goto error_shm_open;
-               }
-               shmfd = shm_open(tmp_name,
-                                O_CREAT | O_EXCL | O_RDWR, 0700);
-       } while (shmfd < 0 && (errno == EEXIST || errno == EACCES));
-       if (shmfd < 0) {
-               PERROR("shm_open");
-               goto error_shm_open;
-       }
-       ret = shm_unlink(tmp_name);
-       if (ret < 0 && errno != ENOENT) {
-               PERROR("shm_unlink");
-               goto error_shm_release;
+
+       if (!shm_path) {
+               obj->shm_path[0] = '\0';
+               shmfd = create_posix_shm();
+       } else {
+               strncpy(obj->shm_path, shm_path,
+                       sizeof(obj->shm_path));
+               obj->shm_path[sizeof(obj->shm_path) - 1] = '\0';
+
+               /* Path should already exist, but could fail. */
+               shmfd = create_shared_file(shm_path);
        }
+       if (shmfd < 0)
+               goto error_shm_open;
+
        sigblocked = 0;
        ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL);
        if (ret == -1) {
@@ -199,7 +238,6 @@ struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table,
 
 error_mmap:
 error_ftruncate:
-error_shm_release:
 error_zero_file:
 error_sigmask_release:
        ret = close(shmfd);
@@ -207,6 +245,12 @@ error_sigmask_release:
                PERROR("close");
                assert(0);
        }
+       if (shm_path) {
+               ret = unlink(shm_path);
+               if (ret) {
+                       PERROR("ret");
+               }
+       }
 error_shm_open:
        if (sigblocked) {
                ret = pthread_sigmask(SIG_SETMASK, &orig_sigs, NULL);
@@ -291,11 +335,13 @@ alloc_error:
 
 struct shm_object *shm_object_table_alloc(struct shm_object_table *table,
                        size_t memory_map_size,
-                       enum shm_object_type type)
+                       enum shm_object_type type,
+                       const char *shm_path)
 {
        switch (type) {
        case SHM_OBJECT_SHM:
-               return _shm_object_table_alloc_shm(table, memory_map_size);
+               return _shm_object_table_alloc_shm(table, memory_map_size,
+                               shm_path);
        case SHM_OBJECT_MEM:
                return _shm_object_table_alloc_mem(table, memory_map_size);
        default:
@@ -416,6 +462,12 @@ void shmp_object_destroy(struct shm_object *obj)
                        PERROR("close");
                        assert(0);
                }
+               if (obj->shm_path[0]) {
+                       ret = unlink(obj->shm_path);
+                       if (ret) {
+                               PERROR("ret");
+                       }
+               }
                for (i = 0; i < 2; i++) {
                        if (obj->wait_fd[i] < 0)
                                continue;
index 8d9d1136469d580c6cec5f1c37af639ce73ef6e0..9253e952dea720de230b894a81e77660f377e5bc 100644 (file)
@@ -88,7 +88,8 @@ void _set_shmp(struct shm_ref *ref, struct shm_ref src)
 struct shm_object_table *shm_object_table_create(size_t max_nb_obj);
 struct shm_object *shm_object_table_alloc(struct shm_object_table *table,
                        size_t memory_map_size,
-                       enum shm_object_type type);
+                       enum shm_object_type type,
+                       const char *shm_path);
 struct shm_object *shm_object_table_append_shm(struct shm_object_table *table,
                        int shm_fd, int wakeup_fd, uint32_t stream_nr,
                        size_t memory_map_size);
index ba7f4b2339d055f2ff13aed7e8f0c139c2267843..e40ba5a5f6aa5a6cbc118ecfe17db5e83cb434c4 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdint.h>
+#include <limits.h>
 #include "shm_internal.h"
 
 struct channel;
@@ -39,6 +40,7 @@ struct shm_object {
        char *memory_map;
        size_t memory_map_size;
        uint64_t allocated_len;
+       char shm_path[PATH_MAX];
 };
 
 struct shm_object_table {
This page took 0.041493 seconds and 4 git commands to generate.