2 * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #include "index-file.h"
19 #include "lttng-relayd.h"
21 #include <common/defaults.h>
22 #include <common/error.h>
23 #include <common/utils.h>
24 #include <common/readwrite.h>
25 #include <common/fd-tracker/fd-tracker.h>
26 #include <common/fd-tracker/utils.h>
27 #include <lttng/constant.h>
35 struct relay_index_file
{
36 struct fs_handle
*handle
;
44 * This unlink wrapper allows the fd_tracker to check if any other
45 * fs_handle references the index before unlinking it. If the relay holds
46 * this file open, it is essential to unlink it through an fs_handle as this
47 * will delay the actual unlink() until all handles have released this file.
49 * The file is renamed and unlinked once the last handle to its inode has been
53 int unlink_through_handle(const char *path
)
55 int ret
= 0, close_ret
;
56 struct fs_handle
*handle
;
58 * Since this operation is only performed to perform the unlink
59 * through the fs_handle and fd-tracker system, the flag is opened
60 * without the O_CREAT. There is no need to perform the unlink if
61 * the file doesn't already exist.
65 DBG("Unlinking index at %s through a filesystem handle", path
);
66 handle
= fd_tracker_open_fs_handle(the_fd_tracker
, path
, flags
, NULL
);
68 if (errno
== ENOENT
) {
69 DBG("File %s does not exist, ignoring unlink", path
);
74 ret
= fs_handle_unlink(handle
);
75 close_ret
= fs_handle_close(handle
);
77 ERR("Failed to close handle after performing an unlink operation on a filesystem handle");
81 DBG("Unlinking index at %s failed with error code %i", path
, ret
);
87 * Create the index file associated with a trace file.
89 * Return allocated struct lttng_index_file, NULL on error.
91 struct relay_index_file
*relay_index_file_create(const char *path_name
,
92 const char *stream_name
, uint64_t size
, uint64_t count
,
93 uint32_t idx_major
, uint32_t idx_minor
)
95 struct relay_index_file
*index_file
;
96 struct fs_handle
*fs_handle
= NULL
;
99 struct ctf_packet_index_file_hdr hdr
;
100 char idx_dir_path
[LTTNG_PATH_MAX
];
101 char idx_file_path
[LTTNG_PATH_MAX
];
103 * With the session rotation feature on the relay, we might need to seek
104 * and truncate a tracefile, so we need read and write access.
106 int flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
107 /* Open with 660 mode */
108 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
110 index_file
= zmalloc(sizeof(*index_file
));
112 PERROR("allocating relay_index_file");
116 ret
= snprintf(idx_dir_path
, sizeof(idx_dir_path
), "%s/" DEFAULT_INDEX_DIR
,
119 PERROR("snprintf index path");
123 /* Create index directory if necessary. */
124 ret
= utils_mkdir(idx_dir_path
, S_IRWXU
| S_IRWXG
, -1, -1);
126 if (errno
!= EEXIST
) {
127 PERROR("Index trace directory creation error");
132 ret
= utils_stream_file_name(idx_file_path
, idx_dir_path
, stream_name
,
133 size
, count
, DEFAULT_INDEX_FILE_SUFFIX
);
135 ERR("Could not build path of index file");
140 * For tracefile rotation. We need to unlink the old
141 * file if present to synchronize with the tail of the
142 * live viewer which could be working on this same file.
143 * By doing so, any reference to the old index file
144 * stays valid even if we re-create a new file with the
145 * same name afterwards.
147 ret
= unlink_through_handle(idx_file_path
);
152 fs_handle
= fd_tracker_open_fs_handle(the_fd_tracker
, idx_file_path
,
155 PERROR("Failed to open index file at %s", idx_file_path
);
158 index_file
->handle
= fs_handle
;
160 fd
= fs_handle_get_fd(fs_handle
);
162 PERROR("Failed to get fd of index file at %s", idx_file_path
);
166 ctf_packet_index_file_hdr_init(&hdr
, idx_major
, idx_minor
);
167 size_ret
= lttng_write(fd
, &hdr
, sizeof(hdr
));
168 if (size_ret
< sizeof(hdr
)) {
169 PERROR("write index header");
173 index_file
->major
= idx_major
;
174 index_file
->minor
= idx_minor
;
175 index_file
->element_len
= ctf_packet_index_len(idx_major
, idx_minor
);
176 urcu_ref_init(&index_file
->ref
);
178 fs_handle_put_fd(fs_handle
);
184 fs_handle_put_fd(fs_handle
);
189 close_ret
= fs_handle_close(fs_handle
);
191 PERROR("Failed to close index filesystem handle");
198 struct relay_index_file
*relay_index_file_open(const char *path_name
,
199 const char *channel_name
, uint64_t tracefile_count
,
200 uint64_t tracefile_count_current
)
202 struct relay_index_file
*index_file
;
205 char fullpath
[PATH_MAX
];
206 struct ctf_packet_index_file_hdr hdr
;
207 uint32_t major
, minor
, element_len
;
208 int flags
= O_RDONLY
;
209 struct fs_handle
*handle
= NULL
;
212 assert(channel_name
);
214 index_file
= zmalloc(sizeof(*index_file
));
216 PERROR("Failed to allocate relay_index_file");
220 if (tracefile_count
> 0) {
221 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s_%"
222 PRIu64 DEFAULT_INDEX_FILE_SUFFIX
, path_name
,
223 channel_name
, tracefile_count_current
);
225 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s"
226 DEFAULT_INDEX_FILE_SUFFIX
, path_name
, channel_name
);
229 PERROR("Failed to build index path");
233 DBG("Index opening file %s in read only mode", fullpath
);
234 handle
= fd_tracker_open_fs_handle(the_fd_tracker
, fullpath
, flags
,
237 PERROR("Failed to open index file at %s", fullpath
);
241 fd
= fs_handle_get_fd(handle
);
243 PERROR("Failed to get fd of index file at %s", fullpath
);
247 read_len
= lttng_read(fd
, &hdr
, sizeof(hdr
));
249 PERROR("Failed to read index header");
253 if (be32toh(hdr
.magic
) != CTF_INDEX_MAGIC
) {
254 ERR("Invalid header magic %#010x, expected %#010x",
255 be32toh(hdr
.magic
), CTF_INDEX_MAGIC
);
258 major
= be32toh(hdr
.index_major
);
259 minor
= be32toh(hdr
.index_minor
);
260 element_len
= be32toh(hdr
.packet_index_len
);
262 if (major
!= CTF_INDEX_MAJOR
) {
263 ERR("Invalid header version, major = %" PRIu32
", expected %i",
264 major
, CTF_INDEX_MAJOR
);
267 if (element_len
> sizeof(struct ctf_packet_index
)) {
268 ERR("Index element length too long (%" PRIu32
" bytes)",
273 fs_handle_put_fd(handle
);
274 index_file
->handle
= handle
;
275 index_file
->major
= major
;
276 index_file
->minor
= minor
;
277 index_file
->element_len
= element_len
;
278 urcu_ref_init(&index_file
->ref
);
284 fs_handle_put_fd(handle
);
286 ret
= fs_handle_close(handle
);
288 PERROR("Failed to close index filesystem handle to %s",
297 int relay_index_file_write(const struct relay_index_file
*index_file
,
298 const struct ctf_packet_index
*element
)
306 fd
= fs_handle_get_fd(index_file
->handle
);
308 PERROR("Failed to get fd from handle");
313 write_ret
= lttng_write(fd
, element
, index_file
->element_len
);
314 if (write_ret
< index_file
->element_len
) {
315 PERROR("Failed to write packet index to index file");
320 fs_handle_put_fd(index_file
->handle
);
325 int relay_index_file_read(const struct relay_index_file
*index_file
,
326 struct ctf_packet_index
*element
)
334 fd
= fs_handle_get_fd(index_file
->handle
);
336 PERROR("Failed to get fd of handle %p", index_file
->handle
);
341 read_ret
= lttng_read(fd
, element
, index_file
->element_len
);
342 if (read_ret
< index_file
->element_len
) {
343 PERROR("Failed to read packet index from file");
348 fs_handle_put_fd(index_file
->handle
);
353 int relay_index_file_seek_end(struct relay_index_file
*index_file
)
358 fd
= fs_handle_get_fd(index_file
->handle
);
360 PERROR("Failed to get fd of handle %p", index_file
->handle
);
365 lseek_ret
= lseek(fd
, 0, SEEK_END
);
370 fs_handle_put_fd(index_file
->handle
);
375 void relay_index_file_get(struct relay_index_file
*index_file
)
377 urcu_ref_get(&index_file
->ref
);
381 void relay_index_file_release(struct urcu_ref
*ref
)
384 struct relay_index_file
*index_file
= caa_container_of(ref
,
385 struct relay_index_file
, ref
);
387 ret
= fs_handle_close(index_file
->handle
);
389 PERROR("Failed to close index file");
394 void relay_index_file_put(struct relay_index_file
*index_file
)
396 urcu_ref_put(&index_file
->ref
, relay_index_file_release
);