fd-tracker Fix: do not warn on index file not found
[lttng-tools.git] / src / bin / lttng-relayd / index-file.c
CommitLineData
f465e978
JG
1/*
2 * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
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.
7 *
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
11 * more details.
12 *
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.
16 */
17
18#include "index-file.h"
19#include "lttng-relayd.h"
20
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>
28
29#include <inttypes.h>
30#include <stdbool.h>
31#include <urcu/ref.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34
35struct relay_index_file {
0b124aaa 36 struct fs_handle *handle;
f465e978
JG
37 uint32_t major;
38 uint32_t minor;
39 uint32_t element_len;
40 struct urcu_ref ref;
41};
42
0b124aaa
JG
43/*
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.
48 *
49 * The file is renamed and unlinked once the last handle to its inode has been
50 * released.
51 */
52static
53int unlink_through_handle(const char *path)
54{
55 int ret = 0, close_ret;
56 struct fs_handle *handle;
57 /*
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.
62 */
63 int flags = O_RDONLY;
64
65 DBG("Unlinking index at %s through a filesystem handle", path);
66 handle = fd_tracker_open_fs_handle(the_fd_tracker, path, flags, NULL);
67 if (!handle) {
9e3d760f
JR
68 if (errno == ENOENT) {
69 DBG("File %s does not exist, ignoring unlink", path);
70 }
0b124aaa
JG
71 goto end;
72 }
73
74 ret = fs_handle_unlink(handle);
75 close_ret = fs_handle_close(handle);
76 if (close_ret) {
77 ERR("Failed to close handle after performing an unlink operation on a filesystem handle");
78 }
79end:
80 if (ret) {
81 DBG("Unlinking index at %s failed with error code %i", path, ret);
82 }
83 return ret;
84}
85
f465e978
JG
86/*
87 * Create the index file associated with a trace file.
88 *
89 * Return allocated struct lttng_index_file, NULL on error.
90 */
91struct 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)
94{
95 struct relay_index_file *index_file;
96 struct fs_handle *fs_handle = NULL;
97 int ret, fd = -1;
98 ssize_t size_ret;
99 struct ctf_packet_index_file_hdr hdr;
100 char idx_dir_path[LTTNG_PATH_MAX];
101 char idx_file_path[LTTNG_PATH_MAX];
102 /*
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.
105 */
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;
109
110 index_file = zmalloc(sizeof(*index_file));
111 if (!index_file) {
112 PERROR("allocating relay_index_file");
113 goto error;
114 }
115
f465e978
JG
116 ret = snprintf(idx_dir_path, sizeof(idx_dir_path), "%s/" DEFAULT_INDEX_DIR,
117 path_name);
118 if (ret < 0) {
119 PERROR("snprintf index path");
120 goto error;
121 }
122
123 /* Create index directory if necessary. */
124 ret = utils_mkdir(idx_dir_path, S_IRWXU | S_IRWXG, -1, -1);
125 if (ret < 0) {
126 if (errno != EEXIST) {
127 PERROR("Index trace directory creation error");
128 goto error;
129 }
130 }
131
132 ret = utils_stream_file_name(idx_file_path, idx_dir_path, stream_name,
133 size, count, DEFAULT_INDEX_FILE_SUFFIX);
134 if (ret < 0) {
135 ERR("Could not build path of index file");
136 goto error;
137 }
138
139 /*
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.
146 */
0b124aaa
JG
147 ret = unlink_through_handle(idx_file_path);
148 if (ret < 0) {
f465e978
JG
149 goto error;
150 }
151
152 fs_handle = fd_tracker_open_fs_handle(the_fd_tracker, idx_file_path,
153 flags, &mode);
154 if (!fs_handle) {
9e3d760f 155 PERROR("Failed to open index file at %s", idx_file_path);
f465e978
JG
156 goto error;
157 }
0b124aaa 158 index_file->handle = fs_handle;
f465e978
JG
159
160 fd = fs_handle_get_fd(fs_handle);
161 if (fd < 0) {
9e3d760f 162 PERROR("Failed to get fd of index file at %s", idx_file_path);
f465e978
JG
163 goto error;
164 }
165
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");
170 goto error;
171 }
172
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);
177
178 fs_handle_put_fd(fs_handle);
179
180 return index_file;
181
182error:
183 if (fd >= 0) {
184 fs_handle_put_fd(fs_handle);
185 }
186 if (fs_handle) {
187 int close_ret;
188
189 close_ret = fs_handle_close(fs_handle);
190 if (close_ret < 0) {
191 PERROR("Failed to close index filesystem handle");
192 }
193 }
194 free(index_file);
195 return NULL;
196}
197
f465e978
JG
198struct 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)
201{
202 struct relay_index_file *index_file;
0b124aaa 203 int ret, fd = -1;
f465e978
JG
204 ssize_t read_len;
205 char fullpath[PATH_MAX];
f465e978
JG
206 struct ctf_packet_index_file_hdr hdr;
207 uint32_t major, minor, element_len;
0b124aaa
JG
208 int flags = O_RDONLY;
209 struct fs_handle *handle = NULL;
f465e978
JG
210
211 assert(path_name);
212 assert(channel_name);
213
214 index_file = zmalloc(sizeof(*index_file));
215 if (!index_file) {
216 PERROR("Failed to allocate relay_index_file");
217 goto error;
218 }
219
f465e978
JG
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);
224 } else {
225 ret = snprintf(fullpath, sizeof(fullpath), "%s/" DEFAULT_INDEX_DIR "/%s"
226 DEFAULT_INDEX_FILE_SUFFIX, path_name, channel_name);
227 }
228 if (ret < 0) {
229 PERROR("Failed to build index path");
230 goto error;
231 }
232
0b124aaa
JG
233 DBG("Index opening file %s in read only mode", fullpath);
234 handle = fd_tracker_open_fs_handle(the_fd_tracker, fullpath, flags,
235 NULL);
236 if (!handle) {
f465e978
JG
237 PERROR("Failed to open index file at %s", fullpath);
238 goto error;
239 }
240
0b124aaa
JG
241 fd = fs_handle_get_fd(handle);
242 if (fd < 0) {
243 PERROR("Failed to get fd of index file at %s", fullpath);
244 goto error;
245 }
246
f465e978
JG
247 read_len = lttng_read(fd, &hdr, sizeof(hdr));
248 if (read_len < 0) {
249 PERROR("Failed to read index header");
250 goto error_close;
251 }
252
253 if (be32toh(hdr.magic) != CTF_INDEX_MAGIC) {
254 ERR("Invalid header magic %#010x, expected %#010x",
255 be32toh(hdr.magic), CTF_INDEX_MAGIC);
256 goto error_close;
257 }
258 major = be32toh(hdr.index_major);
259 minor = be32toh(hdr.index_minor);
260 element_len = be32toh(hdr.packet_index_len);
261
262 if (major != CTF_INDEX_MAJOR) {
263 ERR("Invalid header version, major = %" PRIu32 ", expected %i",
264 major, CTF_INDEX_MAJOR);
265 goto error_close;
266 }
267 if (element_len > sizeof(struct ctf_packet_index)) {
268 ERR("Index element length too long (%" PRIu32 " bytes)",
269 element_len);
270 goto error_close;
271 }
272
0b124aaa
JG
273 fs_handle_put_fd(handle);
274 index_file->handle = handle;
f465e978
JG
275 index_file->major = major;
276 index_file->minor = minor;
277 index_file->element_len = element_len;
278 urcu_ref_init(&index_file->ref);
279
280 return index_file;
281
282error_close:
0b124aaa
JG
283 if (fd >= 0) {
284 fs_handle_put_fd(handle);
285 }
286 ret = fs_handle_close(handle);
f465e978 287 if (ret < 0) {
0b124aaa
JG
288 PERROR("Failed to close index filesystem handle to %s",
289 fullpath);
f465e978
JG
290 }
291
292error:
293 free(index_file);
294 return NULL;
295}
296
297int relay_index_file_write(const struct relay_index_file *index_file,
298 const struct ctf_packet_index *element)
299{
300 int fd, ret;
301 ssize_t write_ret;
302
303 assert(index_file);
304 assert(element);
305
0b124aaa 306 fd = fs_handle_get_fd(index_file->handle);
f465e978 307 if (fd < 0) {
9e3d760f 308 PERROR("Failed to get fd from handle");
f465e978
JG
309 ret = fd;
310 goto end;
311 }
312
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");
316 ret = -1;
317 }
318 ret = 0;
319
0b124aaa 320 fs_handle_put_fd(index_file->handle);
f465e978
JG
321end:
322 return ret;
323}
324
325int relay_index_file_read(const struct relay_index_file *index_file,
326 struct ctf_packet_index *element)
327{
328 int fd, ret;
329 ssize_t read_ret;
330
331 assert(index_file);
332 assert(element);
333
0b124aaa 334 fd = fs_handle_get_fd(index_file->handle);
f465e978 335 if (fd < 0) {
9e3d760f 336 PERROR("Failed to get fd of handle %p", index_file->handle);
f465e978
JG
337 ret = fd;
338 goto end;
339 }
340
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");
344 ret = -1;
345 }
346 ret = 0;
347
0b124aaa 348 fs_handle_put_fd(index_file->handle);
f465e978
JG
349end:
350 return ret;
351}
352
353int relay_index_file_seek_end(struct relay_index_file *index_file)
354{
355 int fd, ret = 0;
356 off_t lseek_ret;
357
0b124aaa 358 fd = fs_handle_get_fd(index_file->handle);
f465e978 359 if (fd < 0) {
9e3d760f 360 PERROR("Failed to get fd of handle %p", index_file->handle);
f465e978
JG
361 ret = fd;
362 goto end;
363 }
364
365 lseek_ret = lseek(fd, 0, SEEK_END);
366 if (lseek_ret < 0) {
367 ret = lseek_ret;
368 }
369
0b124aaa 370 fs_handle_put_fd(index_file->handle);
f465e978
JG
371end:
372 return ret;
373}
374
375void relay_index_file_get(struct relay_index_file *index_file)
376{
377 urcu_ref_get(&index_file->ref);
378}
379
380static
381void relay_index_file_release(struct urcu_ref *ref)
382{
383 int ret;
384 struct relay_index_file *index_file = caa_container_of(ref,
385 struct relay_index_file, ref);
386
0b124aaa 387 ret = fs_handle_close(index_file->handle);
f465e978
JG
388 if (ret < 0) {
389 PERROR("Failed to close index file");
390 }
391 free(index_file);
392}
393
394void relay_index_file_put(struct relay_index_file *index_file)
395{
396 urcu_ref_put(&index_file->ref, relay_index_file_release);
397}
This page took 0.039904 seconds and 5 git commands to generate.