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
);
44 int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser
*ctfser
)
49 BT_LOGD("Increasing stream file's current packet size: "
50 "path=\"%s\", fd=%d, "
51 "offset-in-cur-packet-bits=%" PRIu64
", "
52 "cur-packet-size-bytes=%" PRIu64
,
53 ctfser
->path
->str
, ctfser
->fd
,
54 ctfser
->offset_in_cur_packet_bits
,
55 ctfser
->cur_packet_size_bytes
);
56 ret
= munmap_align(ctfser
->base_mma
);
58 BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
63 ctfser
->cur_packet_size_bytes
+= get_packet_size_increment_bytes(
67 ret
= bt_posix_fallocate(ctfser
->fd
, ctfser
->mmap_offset
,
68 ctfser
->cur_packet_size_bytes
);
69 } while (ret
== EINTR
);
72 BT_LOGE("Failed to preallocate memory space: ret=%d", ret
);
76 mmap_align_ctfser(ctfser
);
77 if (ctfser
->base_mma
== MAP_FAILED
) {
78 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
84 BT_LOGD("Increased packet size: "
85 "path=\"%s\", fd=%d, "
86 "offset-in-cur-packet-bits=%" PRIu64
", "
87 "new-packet-size-bytes=%" PRIu64
,
88 ctfser
->path
->str
, ctfser
->fd
,
89 ctfser
->offset_in_cur_packet_bits
,
90 ctfser
->cur_packet_size_bytes
);
96 int bt_ctfser_init(struct bt_ctfser
*ctfser
, const char *path
, int log_level
)
101 memset(ctfser
, 0, sizeof(*ctfser
));
102 ctfser
->fd
= open(path
, O_RDWR
| O_CREAT
| O_TRUNC
,
103 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
104 ctfser
->log_level
= log_level
;
105 if (ctfser
->fd
< 0) {
106 BT_LOGW_ERRNO("Failed to open stream file for writing",
107 ": path=\"%s\", ret=%d",
113 ctfser
->path
= g_string_new(path
);
119 int bt_ctfser_fini(struct bt_ctfser
*ctfser
)
123 if (ctfser
->fd
== -1) {
127 if (ctfser
->base_mma
) {
129 ret
= munmap_align(ctfser
->base_mma
);
131 BT_LOGE_ERRNO("Failed to unmap stream file",
132 ": ret=%d, size-bytes=%" PRIu64
,
133 ret
, ctfser
->stream_size_bytes
);
137 ctfser
->base_mma
= NULL
;
141 * Truncate the stream file's size to the minimum required to
142 * fit the last packet as we might have grown it too much during
143 * the last memory map.
146 ret
= ftruncate(ctfser
->fd
, ctfser
->stream_size_bytes
);
147 } while (ret
== -1 && errno
== EINTR
);
150 BT_LOGE_ERRNO("Failed to truncate stream file",
151 ": ret=%d, size-bytes=%" PRIu64
,
152 ret
, ctfser
->stream_size_bytes
);
157 ret
= close(ctfser
->fd
);
159 BT_LOGE_ERRNO("Failed to close stream file",
168 g_string_free(ctfser
->path
, TRUE
);
176 int bt_ctfser_open_packet(struct bt_ctfser
*ctfser
)
180 BT_LOGD("Opening packet: path=\"%s\", fd=%d, "
181 "prev-packet-size-bytes=%" PRIu64
,
182 ctfser
->path
->str
, ctfser
->fd
,
183 ctfser
->prev_packet_size_bytes
);
185 if (ctfser
->base_mma
) {
186 /* Unmap old base (previous packet) */
187 ret
= munmap_align(ctfser
->base_mma
);
189 BT_LOGE_ERRNO("Failed to unmap stream file",
190 ": ret=%d, size-bytes=%" PRIu64
,
191 ret
, ctfser
->stream_size_bytes
);
195 ctfser
->base_mma
= NULL
;
199 * Add the previous packet's size to the memory map address
200 * offset to start writing immediately after it.
202 ctfser
->mmap_offset
+= ctfser
->prev_packet_size_bytes
;
203 ctfser
->prev_packet_size_bytes
= 0;
205 /* Make initial space for the current packet */
206 ctfser
->cur_packet_size_bytes
= get_packet_size_increment_bytes(
210 ret
= bt_posix_fallocate(ctfser
->fd
, ctfser
->mmap_offset
,
211 ctfser
->cur_packet_size_bytes
);
212 } while (ret
== EINTR
);
215 BT_LOGE("Failed to preallocate memory space: ret=%d", ret
);
219 /* Start writing at the beginning of the current packet */
220 ctfser
->offset_in_cur_packet_bits
= 0;
222 /* Get new base address */
223 mmap_align_ctfser(ctfser
);
224 if (ctfser
->base_mma
== MAP_FAILED
) {
225 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
231 BT_LOGD("Opened packet: path=\"%s\", fd=%d, "
232 "cur-packet-size-bytes=%" PRIu64
,
233 ctfser
->path
->str
, ctfser
->fd
,
234 ctfser
->cur_packet_size_bytes
);
240 void bt_ctfser_close_current_packet(struct bt_ctfser
*ctfser
,
241 uint64_t packet_size_bytes
)
243 BT_LOGD("Closing packet: path=\"%s\", fd=%d, "
244 "offset-in-cur-packet-bits=%" PRIu64
245 "cur-packet-size-bytes=%" PRIu64
,
246 ctfser
->path
->str
, ctfser
->fd
,
247 ctfser
->offset_in_cur_packet_bits
,
248 ctfser
->cur_packet_size_bytes
);
251 * This will be used during the next call to
252 * bt_ctfser_open_packet(): we add
253 * `ctfser->prev_packet_size_bytes` to the current memory map
254 * address offset (first byte of _this_ packet), effectively
255 * making _this_ packet the required size.
257 ctfser
->prev_packet_size_bytes
= packet_size_bytes
;
258 ctfser
->stream_size_bytes
+= packet_size_bytes
;
259 BT_LOGD("Closed packet: path=\"%s\", fd=%d, "
260 "stream-file-size-bytes=%" PRIu64
,
261 ctfser
->path
->str
, ctfser
->fd
,
262 ctfser
->stream_size_bytes
);