2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * SPDX-License-Identifier: GPL-2.0-only
13 #include <common/common.hpp>
14 #include <common/compat/endian.hpp>
15 #include <common/defaults.hpp>
16 #include <common/utils.hpp>
18 #include <lttng/constant.h>
22 #include <sys/types.h>
24 #define WRITE_FILE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC)
25 #define READ_ONLY_FILE_FLAGS O_RDONLY
27 static enum lttng_trace_chunk_status
28 _lttng_index_file_create_from_trace_chunk(struct lttng_trace_chunk
*chunk
,
29 const char *channel_path
,
30 const char *stream_name
,
31 uint64_t stream_file_size
,
32 uint64_t stream_file_index
,
35 bool unlink_existing_file
,
38 struct lttng_index_file
**file
)
40 struct lttng_index_file
*index_file
;
41 enum lttng_trace_chunk_status chunk_status
;
43 struct fs_handle
*fs_handle
= nullptr;
45 struct ctf_packet_index_file_hdr hdr
;
46 char index_directory_path
[LTTNG_PATH_MAX
];
47 char index_file_path
[LTTNG_PATH_MAX
];
48 const mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
49 const bool acquired_reference
= lttng_trace_chunk_get(chunk
);
50 const char *separator
;
52 LTTNG_ASSERT(acquired_reference
);
54 index_file
= zmalloc
<lttng_index_file
>();
56 PERROR("Failed to allocate lttng_index_file");
57 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
61 index_file
->trace_chunk
= chunk
;
62 if (channel_path
[0] == '\0') {
67 ret
= snprintf(index_directory_path
,
68 sizeof(index_directory_path
),
69 "%s%s" DEFAULT_INDEX_DIR
,
72 if (ret
< 0 || ret
>= sizeof(index_directory_path
)) {
73 ERR("Failed to format index directory path");
74 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
78 ret
= utils_stream_file_path(index_directory_path
,
82 DEFAULT_INDEX_FILE_SUFFIX
,
84 sizeof(index_file_path
));
86 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
90 if (unlink_existing_file
) {
92 * For tracefile rotation. We need to unlink the old
93 * file if present to synchronize with the tail of the
94 * live viewer which could be working on this same file.
95 * By doing so, any reference to the old index file
96 * stays valid even if we re-create a new file with the
97 * same name afterwards.
99 chunk_status
= (lttng_trace_chunk_status
) lttng_trace_chunk_unlink_file(
100 chunk
, index_file_path
);
101 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
&&
102 !(chunk_status
== LTTNG_TRACE_CHUNK_STATUS_ERROR
&& errno
== ENOENT
)) {
107 chunk_status
= lttng_trace_chunk_open_fs_handle(
108 chunk
, index_file_path
, flags
, mode
, &fs_handle
, expect_no_file
);
109 if (chunk_status
!= LTTNG_TRACE_CHUNK_STATUS_OK
) {
113 if (flags
== WRITE_FILE_FLAGS
) {
114 ctf_packet_index_file_hdr_init(&hdr
, index_major
, index_minor
);
115 size_ret
= fs_handle_write(fs_handle
, &hdr
, sizeof(hdr
));
116 if (size_ret
< sizeof(hdr
)) {
117 PERROR("Failed to write index header");
118 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
121 index_file
->element_len
= ctf_packet_index_len(index_major
, index_minor
);
123 uint32_t element_len
;
125 size_ret
= fs_handle_read(fs_handle
, &hdr
, sizeof(hdr
));
127 PERROR("Failed to read index header");
128 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
131 if (be32toh(hdr
.magic
) != CTF_INDEX_MAGIC
) {
132 ERR("Invalid header magic");
133 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
136 if (index_major
!= be32toh(hdr
.index_major
)) {
137 ERR("Index major number mismatch: %u, expect %u",
138 be32toh(hdr
.index_major
),
140 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
143 if (index_minor
!= be32toh(hdr
.index_minor
)) {
144 ERR("Index minor number mismatch: %u, expect %u",
145 be32toh(hdr
.index_minor
),
147 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
150 element_len
= be32toh(hdr
.packet_index_len
);
151 if (element_len
> sizeof(struct ctf_packet_index
)) {
152 ERR("Index element length too long");
153 chunk_status
= LTTNG_TRACE_CHUNK_STATUS_ERROR
;
156 index_file
->element_len
= element_len
;
158 index_file
->file
= fs_handle
;
159 index_file
->major
= index_major
;
160 index_file
->minor
= index_minor
;
161 urcu_ref_init(&index_file
->ref
);
164 return LTTNG_TRACE_CHUNK_STATUS_OK
;
168 ret
= fs_handle_close(fs_handle
);
170 PERROR("Failed to close file descriptor of index file");
173 lttng_trace_chunk_put(chunk
);
178 enum lttng_trace_chunk_status
179 lttng_index_file_create_from_trace_chunk(struct lttng_trace_chunk
*chunk
,
180 const char *channel_path
,
181 const char *stream_name
,
182 uint64_t stream_file_size
,
183 uint64_t stream_file_index
,
184 uint32_t index_major
,
185 uint32_t index_minor
,
186 bool unlink_existing_file
,
187 struct lttng_index_file
**file
)
189 return _lttng_index_file_create_from_trace_chunk(chunk
,
196 unlink_existing_file
,
202 enum lttng_trace_chunk_status
203 lttng_index_file_create_from_trace_chunk_read_only(struct lttng_trace_chunk
*chunk
,
204 const char *channel_path
,
205 const char *stream_name
,
206 uint64_t stream_file_size
,
207 uint64_t stream_file_index
,
208 uint32_t index_major
,
209 uint32_t index_minor
,
211 struct lttng_index_file
**file
)
213 return _lttng_index_file_create_from_trace_chunk(chunk
,
221 READ_ONLY_FILE_FLAGS
,
227 * Write index values to the given index file.
229 * Return 0 on success, -1 on error.
231 int lttng_index_file_write(const struct lttng_index_file
*index_file
,
232 const struct ctf_packet_index
*element
)
235 const size_t len
= index_file
->element_len
;
238 LTTNG_ASSERT(index_file
);
239 LTTNG_ASSERT(element
);
241 if (!index_file
->file
) {
245 ret
= fs_handle_write(index_file
->file
, element
, len
);
247 PERROR("writing index file");
257 * Read index values from the given index file.
259 * Return 0 on success, -1 on error.
261 int lttng_index_file_read(const struct lttng_index_file
*index_file
,
262 struct ctf_packet_index
*element
)
265 const size_t len
= index_file
->element_len
;
267 LTTNG_ASSERT(element
);
269 if (!index_file
->file
) {
273 ret
= fs_handle_read(index_file
->file
, element
, len
);
275 PERROR("read index file");
279 ERR("lttng_read expected %zu, returned %zd", len
, ret
);
288 void lttng_index_file_get(struct lttng_index_file
*index_file
)
290 urcu_ref_get(&index_file
->ref
);
293 static void lttng_index_file_release(struct urcu_ref
*ref
)
295 struct lttng_index_file
*index_file
= caa_container_of(ref
, struct lttng_index_file
, ref
);
297 if (fs_handle_close(index_file
->file
)) {
298 PERROR("close index fd");
300 lttng_trace_chunk_put(index_file
->trace_chunk
);
304 void lttng_index_file_put(struct lttng_index_file
*index_file
)
306 urcu_ref_put(&index_file
->ref
, lttng_index_file_release
);