2 * Copyright (C) 2015 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 * 2018 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License, version 2 only, as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <common/common.h>
25 #include <common/fd-tracker/fd-tracker.h>
26 #include <common/fd-tracker/utils.h>
27 #include <common/utils.h>
29 #include "stream-fd.h"
30 #include "lttng-relayd.h"
36 struct fs_handle
*handle
;
43 static struct stream_fd
*_stream_fd_alloc(void)
47 sf
= zmalloc(sizeof(*sf
));
51 urcu_ref_init(&sf
->ref
);
56 static struct stream_fd
*stream_fd_suspendable_create(struct fs_handle
*handle
)
58 struct stream_fd
*stream_fd
= _stream_fd_alloc();
64 stream_fd
->suspendable
= true;
65 stream_fd
->u
.handle
= handle
;
70 static struct stream_fd
*stream_fd_unsuspendable_create(int fd
)
72 struct stream_fd
*stream_fd
= _stream_fd_alloc();
78 stream_fd
->suspendable
= false;
84 static int open_file(void *data
, int *out_fd
)
87 const char *path
= data
;
89 ret
= open(path
, O_RDONLY
);
100 * Stream files are opened (read-only) on the live end of the relayd.
101 * In live mode, it is expected that a client is able to consume a
102 * complete file even if it is replaced (in file rotation mode).
104 * Thus, it is not possible to open those files as suspendable file
105 * handles. This means that live clients can keep a large number of
106 * open file descriptors. As a work-around, we could create hard links
107 * to the files to make the files suspendable. The original file would be
108 * replaced, but the viewer's hard-link would ensure that the inode is
109 * still available for restoration.
111 * The main roadblock to this approach is validating that the trace
112 * directory resides in a filesystem that supports hard-links. Otherwise,
113 * a cooperative mechanism could allow the viewer end to mark a file as
114 * being in use and it could be renamed rather than unlinked by the
117 struct stream_fd
*stream_fd_open(const char *path
)
120 struct stream_fd
*stream_fd
= NULL
;
122 ret
= fd_tracker_open_unsuspendable_fd(the_fd_tracker
, &fd
,
123 (const char **) &path
, 1,
124 open_file
, (void *) path
);
129 stream_fd
= stream_fd_unsuspendable_create(fd
);
131 (void) fd_tracker_close_unsuspendable_fd(the_fd_tracker
, &fd
, 1,
132 fd_tracker_util_close_fd
, NULL
);
139 struct fs_handle
*create_fs_handle(const char *path
)
141 struct fs_handle
*handle
;
143 * With the session rotation feature on the relay, we might need to seek
144 * and truncate a tracefile, so we need read and write access.
146 int flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
147 /* Open with 660 mode */
148 mode_t mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
;
150 handle
= fd_tracker_open_fs_handle(the_fd_tracker
, path
, flags
, &mode
);
152 ERR("Failed to open fs handle to %s", path
);
159 * Stream file are created by on the consumerd/data-reception end. Those
160 * stream fds can be suspended as there is no expectation that the files
161 * will be unlinked and then need to be appended-to.
163 * Hence, the file descriptors are created as suspendable to allow the
164 * fd-tracker to reduce the number of active fds..
166 struct stream_fd
*stream_fd_create(const char *path_name
, const char *file_name
,
167 uint64_t size
, uint64_t count
, const char *suffix
)
169 struct stream_fd
*stream_fd
= NULL
;
170 struct fs_handle
*handle
;
174 ret
= utils_stream_file_name(path
, path_name
, file_name
,
175 size
, count
, suffix
);
180 handle
= create_fs_handle(path
);
185 stream_fd
= stream_fd_suspendable_create(handle
);
187 (void) fs_handle_close(handle
);
194 int stream_fd_rotate(struct stream_fd
*stream_fd
, const char *path_name
,
195 const char *file_name
, uint64_t size
,
196 uint64_t count
, uint64_t *new_count
)
203 assert(stream_fd
->suspendable
);
205 utils_stream_file_rotation_get_new_count(count
, new_count
,
208 ret
= utils_stream_file_name(path
, path_name
, file_name
,
214 ret
= fs_handle_close(stream_fd
->u
.handle
);
215 stream_fd
->u
.handle
= NULL
;
217 PERROR("Closing stream tracefile handle");
223 if (ret
< 0 && errno
!= ENOENT
) {
228 ret
= utils_stream_file_name(path
, path_name
, file_name
,
229 size
, new_count
? *new_count
: 0, NULL
);
234 stream_fd
->u
.handle
= create_fs_handle(path
);
235 if (!stream_fd
->u
.handle
) {
246 void stream_fd_get(struct stream_fd
*sf
)
248 urcu_ref_get(&sf
->ref
);
251 static void stream_fd_release(struct urcu_ref
*ref
)
253 struct stream_fd
*sf
= caa_container_of(ref
, struct stream_fd
, ref
);
256 if (sf
->suspendable
) {
257 ret
= fs_handle_close(sf
->u
.handle
);
259 ret
= fd_tracker_close_unsuspendable_fd(the_fd_tracker
, &sf
->u
.fd
,
260 1, fd_tracker_util_close_fd
, NULL
);
263 PERROR("Error closing stream handle");
268 void stream_fd_put(struct stream_fd
*sf
)
270 urcu_ref_put(&sf
->ref
, stream_fd_release
);
273 int stream_fd_get_fd(struct stream_fd
*sf
)
275 return sf
->suspendable
? fs_handle_get_fd(sf
->u
.handle
) : sf
->u
.fd
;
278 void stream_fd_put_fd(struct stream_fd
*sf
)
280 if (sf
->suspendable
) {
281 fs_handle_put_fd(sf
->u
.handle
);
This page took 0.037739 seconds and 6 git commands to generate.