2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
7 #define BT_LOG_OUTPUT_LEVEL (ctfser->log_level)
8 #define BT_LOG_TAG "CTFSER"
9 #include "logging/log.h"
14 #include <sys/types.h>
17 #include "common/assert.h"
24 #include "common/macros.h"
25 #include "common/common.h"
26 #include "ctfser/ctfser.h"
27 #include "compat/unistd.h"
28 #include "compat/fcntl.h"
31 uint64_t get_packet_size_increment_bytes(struct bt_ctfser
*ctfser
)
33 return bt_common_get_page_size(ctfser
->log_level
) * 8;
37 void mmap_align_ctfser(struct bt_ctfser
*ctfser
)
39 ctfser
->base_mma
= mmap_align(ctfser
->cur_packet_size_bytes
,
40 PROT_READ
| PROT_WRITE
,
41 MAP_SHARED
, ctfser
->fd
, ctfser
->mmap_offset
, ctfser
->log_level
);
45 int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser
*ctfser
)
50 BT_LOGD("Increasing stream file's current packet size: "
51 "path=\"%s\", fd=%d, "
52 "offset-in-cur-packet-bits=%" PRIu64
", "
53 "cur-packet-size-bytes=%" PRIu64
,
54 ctfser
->path
->str
, ctfser
->fd
,
55 ctfser
->offset_in_cur_packet_bits
,
56 ctfser
->cur_packet_size_bytes
);
57 ret
= munmap_align(ctfser
->base_mma
);
59 BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
64 ctfser
->cur_packet_size_bytes
+= get_packet_size_increment_bytes(
68 ret
= bt_posix_fallocate(ctfser
->fd
, ctfser
->mmap_offset
,
69 ctfser
->cur_packet_size_bytes
);
70 } while (ret
== EINTR
);
73 BT_LOGE("Failed to preallocate memory space: ret=%d", ret
);
77 mmap_align_ctfser(ctfser
);
78 if (ctfser
->base_mma
== MAP_FAILED
) {
79 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
85 BT_LOGD("Increased packet size: "
86 "path=\"%s\", fd=%d, "
87 "offset-in-cur-packet-bits=%" PRIu64
", "
88 "new-packet-size-bytes=%" PRIu64
,
89 ctfser
->path
->str
, ctfser
->fd
,
90 ctfser
->offset_in_cur_packet_bits
,
91 ctfser
->cur_packet_size_bytes
);
98 int bt_ctfser_init(struct bt_ctfser
*ctfser
, const char *path
, int log_level
)
103 memset(ctfser
, 0, sizeof(*ctfser
));
104 ctfser
->fd
= open(path
, O_RDWR
| O_CREAT
| O_TRUNC
,
105 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
106 ctfser
->log_level
= log_level
;
107 if (ctfser
->fd
< 0) {
108 BT_LOGW_ERRNO("Failed to open stream file for writing",
109 ": path=\"%s\", ret=%d",
115 ctfser
->path
= g_string_new(path
);
122 int bt_ctfser_fini(struct bt_ctfser
*ctfser
)
126 if (ctfser
->fd
== -1) {
130 if (ctfser
->base_mma
) {
132 ret
= munmap_align(ctfser
->base_mma
);
134 BT_LOGE_ERRNO("Failed to unmap stream file",
135 ": ret=%d, size-bytes=%" PRIu64
,
136 ret
, ctfser
->stream_size_bytes
);
140 ctfser
->base_mma
= NULL
;
144 * Truncate the stream file's size to the minimum required to
145 * fit the last packet as we might have grown it too much during
146 * the last memory map.
149 ret
= ftruncate(ctfser
->fd
, ctfser
->stream_size_bytes
);
150 } while (ret
== -1 && errno
== EINTR
);
153 BT_LOGE_ERRNO("Failed to truncate stream file",
154 ": ret=%d, size-bytes=%" PRIu64
,
155 ret
, ctfser
->stream_size_bytes
);
160 ret
= close(ctfser
->fd
);
162 BT_LOGE_ERRNO("Failed to close stream file",
171 g_string_free(ctfser
->path
, TRUE
);
180 int bt_ctfser_open_packet(struct bt_ctfser
*ctfser
)
184 BT_LOGD("Opening packet: path=\"%s\", fd=%d, "
185 "prev-packet-size-bytes=%" PRIu64
,
186 ctfser
->path
->str
, ctfser
->fd
,
187 ctfser
->prev_packet_size_bytes
);
189 if (ctfser
->base_mma
) {
190 /* Unmap old base (previous packet) */
191 ret
= munmap_align(ctfser
->base_mma
);
193 BT_LOGE_ERRNO("Failed to unmap stream file",
194 ": ret=%d, size-bytes=%" PRIu64
,
195 ret
, ctfser
->stream_size_bytes
);
199 ctfser
->base_mma
= NULL
;
203 * Add the previous packet's size to the memory map address
204 * offset to start writing immediately after it.
206 ctfser
->mmap_offset
+= ctfser
->prev_packet_size_bytes
;
207 ctfser
->prev_packet_size_bytes
= 0;
209 /* Make initial space for the current packet */
210 ctfser
->cur_packet_size_bytes
= get_packet_size_increment_bytes(
214 ret
= bt_posix_fallocate(ctfser
->fd
, ctfser
->mmap_offset
,
215 ctfser
->cur_packet_size_bytes
);
216 } while (ret
== EINTR
);
219 BT_LOGE("Failed to preallocate memory space: ret=%d", ret
);
223 /* Start writing at the beginning of the current packet */
224 ctfser
->offset_in_cur_packet_bits
= 0;
226 /* Get new base address */
227 mmap_align_ctfser(ctfser
);
228 if (ctfser
->base_mma
== MAP_FAILED
) {
229 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
235 BT_LOGD("Opened packet: path=\"%s\", fd=%d, "
236 "cur-packet-size-bytes=%" PRIu64
,
237 ctfser
->path
->str
, ctfser
->fd
,
238 ctfser
->cur_packet_size_bytes
);
245 void bt_ctfser_close_current_packet(struct bt_ctfser
*ctfser
,
246 uint64_t packet_size_bytes
)
248 BT_LOGD("Closing packet: path=\"%s\", fd=%d, "
249 "offset-in-cur-packet-bits=%" PRIu64
250 "cur-packet-size-bytes=%" PRIu64
,
251 ctfser
->path
->str
, ctfser
->fd
,
252 ctfser
->offset_in_cur_packet_bits
,
253 ctfser
->cur_packet_size_bytes
);
256 * This will be used during the next call to
257 * bt_ctfser_open_packet(): we add
258 * `ctfser->prev_packet_size_bytes` to the current memory map
259 * address offset (first byte of _this_ packet), effectively
260 * making _this_ packet the required size.
262 ctfser
->prev_packet_size_bytes
= packet_size_bytes
;
263 ctfser
->stream_size_bytes
+= packet_size_bytes
;
264 BT_LOGD("Closed packet: path=\"%s\", fd=%d, "
265 "stream-file-size-bytes=%" PRIu64
,
266 ctfser
->path
->str
, ctfser
->fd
,
267 ctfser
->stream_size_bytes
);