/* * ustctl closes the shm_fd fds after mapping it. */ struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle, int cpu) { struct channel *chan = handle->shadow_chan; int *shm_fd, *wait_fd; uint64_t *memory_map_size; struct lttng_ust_lib_ring_buffer *buf; int ret; if (!handle) return NULL; buf = channel_get_ring_buffer(&chan->backend.config, chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size); if (!buf) return NULL; ret = lib_ring_buffer_open_read(buf, handle, 1); if (ret) return NULL; /* * We can close shm_fd early, right after is has been mapped. */ if (*shm_fd >= 0) { ret = close(*shm_fd); if (ret) { perror("Error closing shm_fd"); } *shm_fd = -1; } return buf; }
struct ustctl_consumer_stream * ustctl_create_stream(struct ustctl_consumer_channel *channel, int cpu) { struct ustctl_consumer_stream *stream; struct lttng_ust_shm_handle *handle; struct channel *chan; int shm_fd, wait_fd, wakeup_fd; uint64_t memory_map_size; struct lttng_ust_lib_ring_buffer *buf; int ret; if (!channel) return NULL; handle = channel->chan->handle; if (!handle) return NULL; chan = channel->chan->chan; buf = channel_get_ring_buffer(&chan->backend.config, chan, cpu, handle, &shm_fd, &wait_fd, &wakeup_fd, &memory_map_size); if (!buf) return NULL; ret = lib_ring_buffer_open_read(buf, handle); if (ret) return NULL; stream = zmalloc(sizeof(*stream)); if (!stream) goto alloc_error; stream->handle = handle; stream->buf = buf; stream->chan = channel; stream->shm_fd = shm_fd; stream->wait_fd = wait_fd; stream->wakeup_fd = wakeup_fd; stream->memory_map_size = memory_map_size; stream->cpu = cpu; return stream; alloc_error: return NULL; }
/* * This is not used by anonymous file descriptors. This code is left * there if we ever want to implement an inode with open() operation. */ int lib_ring_buffer_open(struct inode *inode, struct file *file, struct lib_ring_buffer *buf) { int ret; if (!buf) return -EINVAL; ret = lib_ring_buffer_open_read(buf); if (ret) return ret; ret = nonseekable_open(inode, file); if (ret) goto release_read; return 0; release_read: lib_ring_buffer_release_read(buf); return ret; }
static int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile) { struct channel *chan; struct lttng_ust_lib_ring_buffer *buf; int outfd, ret; int *shm_fd, *wait_fd; uint64_t *memory_map_size; chan = shmp(handle, handle->chan); /* open stream */ buf = channel_get_ring_buffer(&chan->backend.config, chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size); if (!buf) return -ENOENT; ret = lib_ring_buffer_open_read(buf, handle, 1); if (ret) { return -1; } /* copy */ outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (outfd < 0) { perror("open output"); return -1; } printf("Waiting for buffer data for %s\n", outfile); for (;;) { unsigned long read_size; unsigned long copy_size; char *ptr; ret = lib_ring_buffer_get_next_subbuf(buf, handle); printf("get next ret %d\n", ret); if (ret == -ENODATA) break; if (ret == -EAGAIN) { sleep(1); continue; } if (ret) { printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret); return -1; } read_size = lib_ring_buffer_get_read_data_size( &chan->backend.config, buf, handle); read_size = PAGE_ALIGN(read_size); ptr = lib_ring_buffer_read_offset_address( &buf->backend, 0, handle); printf("WRITE: copy %lu bytes\n", read_size); copy_size = write(outfd, ptr, read_size); if (copy_size < read_size) { printf("write issue: copied %lu, expected %lu\n", copy_size, read_size); } lib_ring_buffer_put_next_subbuf(buf, handle); } ret = close(outfd); if (ret) { perror("close"); return -1; } /* close stream */ lib_ring_buffer_release_read(buf, handle, 1); return 0; }