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 /* There is nothing to do. */
69 DBG("File %s does not exist, ignoring unlink", path
);
73 ret
= fs_handle_unlink(handle
);
74 close_ret
= fs_handle_close(handle
);
76 ERR("Failed to close handle after performing an unlink operation on a filesystem handle");
80 DBG("Unlinking index at %s failed with error code %i", path
, ret
);
86 * Create the index file associated with a trace file.
88 * Return allocated struct lttng_index_file, NULL on error.
90 struct relay_index_file
*relay_index_file_create(const char *path_name
,
91 const char *stream_name
, uint64_t size
, uint64_t count
,
92 uint32_t idx_major
, uint32_t idx_minor
)
94 struct relay_index_file
*index_file
;
95 struct fs_handle
*fs_handle
= NULL
;
98 struct ctf_packet_index_file_hdr hdr
;
99 char idx_dir_path
[LTTNG_PATH_MAX
];
100 char idx_file_path
[LTTNG_PATH_MAX
];
102 * With the session rotation feature on the relay, we might need to seek
103 * and truncate a tracefile, so we need read and write access.
105 int flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
106 /* Open with 660 mode */
107 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
109 index_file
= zmalloc(sizeof(*index_file
));
111 PERROR("allocating relay_index_file");
115 ret
= snprintf(idx_dir_path
, sizeof(idx_dir_path
), "%s/" DEFAULT_INDEX_DIR
,
118 PERROR("snprintf index path");
122 /* Create index directory if necessary. */
123 ret
= utils_mkdir(idx_dir_path
, S_IRWXU
| S_IRWXG
, -1, -1);
125 if (errno
!= EEXIST
) {
126 PERROR("Index trace directory creation error");
131 ret
= utils_stream_file_name(idx_file_path
, idx_dir_path
, stream_name
,
132 size
, count
, DEFAULT_INDEX_FILE_SUFFIX
);
134 ERR("Could not build path of index file");
139 * For tracefile rotation. We need to unlink the old
140 * file if present to synchronize with the tail of the
141 * live viewer which could be working on this same file.
142 * By doing so, any reference to the old index file
143 * stays valid even if we re-create a new file with the
144 * same name afterwards.
146 ret
= unlink_through_handle(idx_file_path
);
151 fs_handle
= fd_tracker_open_fs_handle(the_fd_tracker
, idx_file_path
,
156 index_file
->handle
= fs_handle
;
158 fd
= fs_handle_get_fd(fs_handle
);
163 ctf_packet_index_file_hdr_init(&hdr
, idx_major
, idx_minor
);
164 size_ret
= lttng_write(fd
, &hdr
, sizeof(hdr
));
165 if (size_ret
< sizeof(hdr
)) {
166 PERROR("write index header");
170 index_file
->major
= idx_major
;
171 index_file
->minor
= idx_minor
;
172 index_file
->element_len
= ctf_packet_index_len(idx_major
, idx_minor
);
173 urcu_ref_init(&index_file
->ref
);
175 fs_handle_put_fd(fs_handle
);
181 fs_handle_put_fd(fs_handle
);
186 close_ret
= fs_handle_close(fs_handle
);
188 PERROR("Failed to close index filesystem handle");
195 struct relay_index_file
*relay_index_file_open(const char *path_name
,
196 const char *channel_name
, uint64_t tracefile_count
,
197 uint64_t tracefile_count_current
)
199 struct relay_index_file
*index_file
;
202 char fullpath
[PATH_MAX
];
203 struct ctf_packet_index_file_hdr hdr
;
204 uint32_t major
, minor
, element_len
;
205 int flags
= O_RDONLY
;
206 struct fs_handle
*handle
= NULL
;
209 assert(channel_name
);
211 index_file
= zmalloc(sizeof(*index_file
));
213 PERROR("Failed to allocate relay_index_file");
217 if (tracefile_count
> 0) {
218 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s_%"
219 PRIu64 DEFAULT_INDEX_FILE_SUFFIX
, path_name
,
220 channel_name
, tracefile_count_current
);
222 ret
= snprintf(fullpath
, sizeof(fullpath
), "%s/" DEFAULT_INDEX_DIR
"/%s"
223 DEFAULT_INDEX_FILE_SUFFIX
, path_name
, channel_name
);
226 PERROR("Failed to build index path");
230 DBG("Index opening file %s in read only mode", fullpath
);
231 handle
= fd_tracker_open_fs_handle(the_fd_tracker
, fullpath
, flags
,
234 PERROR("Failed to open index file at %s", fullpath
);
238 fd
= fs_handle_get_fd(handle
);
240 PERROR("Failed to get fd of index file at %s", fullpath
);
244 read_len
= lttng_read(fd
, &hdr
, sizeof(hdr
));
246 PERROR("Failed to read index header");
250 if (be32toh(hdr
.magic
) != CTF_INDEX_MAGIC
) {
251 ERR("Invalid header magic %#010x, expected %#010x",
252 be32toh(hdr
.magic
), CTF_INDEX_MAGIC
);
255 major
= be32toh(hdr
.index_major
);
256 minor
= be32toh(hdr
.index_minor
);
257 element_len
= be32toh(hdr
.packet_index_len
);
259 if (major
!= CTF_INDEX_MAJOR
) {
260 ERR("Invalid header version, major = %" PRIu32
", expected %i",
261 major
, CTF_INDEX_MAJOR
);
264 if (element_len
> sizeof(struct ctf_packet_index
)) {
265 ERR("Index element length too long (%" PRIu32
" bytes)",
270 fs_handle_put_fd(handle
);
271 index_file
->handle
= handle
;
272 index_file
->major
= major
;
273 index_file
->minor
= minor
;
274 index_file
->element_len
= element_len
;
275 urcu_ref_init(&index_file
->ref
);
281 fs_handle_put_fd(handle
);
283 ret
= fs_handle_close(handle
);
285 PERROR("Failed to close index filesystem handle to %s",
294 int relay_index_file_write(const struct relay_index_file
*index_file
,
295 const struct ctf_packet_index
*element
)
303 fd
= fs_handle_get_fd(index_file
->handle
);
309 write_ret
= lttng_write(fd
, element
, index_file
->element_len
);
310 if (write_ret
< index_file
->element_len
) {
311 PERROR("Failed to write packet index to index file");
316 fs_handle_put_fd(index_file
->handle
);
321 int relay_index_file_read(const struct relay_index_file
*index_file
,
322 struct ctf_packet_index
*element
)
330 fd
= fs_handle_get_fd(index_file
->handle
);
336 read_ret
= lttng_read(fd
, element
, index_file
->element_len
);
337 if (read_ret
< index_file
->element_len
) {
338 PERROR("Failed to read packet index from file");
343 fs_handle_put_fd(index_file
->handle
);
348 int relay_index_file_seek_end(struct relay_index_file
*index_file
)
353 fd
= fs_handle_get_fd(index_file
->handle
);
359 lseek_ret
= lseek(fd
, 0, SEEK_END
);
364 fs_handle_put_fd(index_file
->handle
);
369 void relay_index_file_get(struct relay_index_file
*index_file
)
371 urcu_ref_get(&index_file
->ref
);
375 void relay_index_file_release(struct urcu_ref
*ref
)
378 struct relay_index_file
*index_file
= caa_container_of(ref
,
379 struct relay_index_file
, ref
);
381 ret
= fs_handle_close(index_file
->handle
);
383 PERROR("Failed to close index file");
388 void relay_index_file_put(struct relay_index_file
*index_file
)
390 urcu_ref_put(&index_file
->ref
, relay_index_file_release
);