From: Jérémie Galarneau Date: Wed, 22 Jul 2020 19:29:17 +0000 (-0400) Subject: Add fd_handle interface X-Git-Tag: v2.13.0-rc1~564 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=dd1bac00c933616842aaf51ad4c4240ccee98838;p=lttng-tools.git Add fd_handle interface An fd_handle allows the reference counting of file descriptors which may be shared by multiple objects. There is no synchronization imposed (or provided) for the use of the underlying file descriptors as this utility meant to be used on file descriptors where this would not make sense (eventfd, dir fd, etc.) Signed-off-by: Jérémie Galarneau Change-Id: I1bdeb48caddda125aa8f41afd502df2eb4a0b8b2 --- diff --git a/src/common/Makefile.am b/src/common/Makefile.am index d071bdfdf..49e9a8fd8 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -49,6 +49,7 @@ libcommon_la_SOURCES = \ evaluation.c \ event.c \ filter.c filter.h \ + fd-handle.c fd-handle.h \ fs-handle.c fs-handle.h fs-handle-internal.h \ futex.c futex.h \ location.c \ diff --git a/src/common/fd-handle.c b/src/common/fd-handle.c new file mode 100644 index 000000000..a9c7be4a9 --- /dev/null +++ b/src/common/fd-handle.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include + +#include "fd-handle.h" +#include + +struct fd_handle { + struct urcu_ref ref; + int fd; +}; + +static void fd_handle_release(struct urcu_ref *ref) +{ + int ret; + struct fd_handle *handle = container_of(ref, struct fd_handle, ref); + + assert(handle->fd >= 0); + ret = close(handle->fd); + if (ret == -1) { + PERROR("Failed to close file descriptor of fd_handle upon release: fd = %d", + handle->fd); + } + + free(handle); +} + +LTTNG_HIDDEN +struct fd_handle *fd_handle_create(int fd) +{ + struct fd_handle *handle = NULL; + + if (fd < 0) { + ERR("Attempted to create an fd_handle from an invalid file descriptor: fd = %d", + fd); + goto end; + } + + handle = zmalloc(sizeof(*handle)); + if (!handle) { + PERROR("Failed to allocate fd_handle"); + goto end; + } + + urcu_ref_init(&handle->ref); + handle->fd = fd; + +end: + return handle; +} + +LTTNG_HIDDEN +void fd_handle_get(struct fd_handle *handle) +{ + assert(handle); + urcu_ref_get(&handle->ref); +} + +LTTNG_HIDDEN +void fd_handle_put(struct fd_handle *handle) +{ + assert(handle); + urcu_ref_put(&handle->ref, fd_handle_release); +} + +LTTNG_HIDDEN +int fd_handle_get_fd(struct fd_handle *handle) +{ + assert(handle); + return handle->fd; +} + +LTTNG_HIDDEN +struct fd_handle *fd_handle_copy(const struct fd_handle *handle) +{ + struct fd_handle *new_handle = NULL; + const int new_fd = dup(handle->fd); + + if (new_fd < 0) { + PERROR("Failed to duplicate file descriptor while copying fd_handle: fd = %d", handle->fd); + goto end; + } + + new_handle = fd_handle_create(new_fd); +end: + return new_handle; +} diff --git a/src/common/fd-handle.h b/src/common/fd-handle.h new file mode 100644 index 000000000..4463f3005 --- /dev/null +++ b/src/common/fd-handle.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 Jérémie Galarneau + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef FD_HANDLE_H +#define FD_HANDLE_H + +#include + +/* + * Wrapper around a file descriptor providing reference counting semantics. + * + * An fd_handle will close() the underlying file descriptor when its reference + * count reaches zero. + */ +struct fd_handle; + +/* Create a file descriptor handle. */ +LTTNG_HIDDEN +struct fd_handle *fd_handle_create(int fd); + +/* Acquire reference to a file descriptor handle. */ +LTTNG_HIDDEN +void fd_handle_get(struct fd_handle *handle); + +/* Release reference to a file descriptor handle. */ +LTTNG_HIDDEN +void fd_handle_put(struct fd_handle *handle); + +/* + * Return the underlying file descriptor of a file descriptor handle. + * + * This function can't fail. + */ +LTTNG_HIDDEN +int fd_handle_get_fd(struct fd_handle *handle); + +/* + * Obtain a copy of a file descriptor handle. + * + * On success, the caller becomes the sole owner of the returned file descriptor + * handle. The underlying file descriptor is duplicated using dup(). Refer to + * the system documentation for the semantics of dup() for this particular file + * descriptor type. + */ +LTTNG_HIDDEN +struct fd_handle *fd_handle_copy(const struct fd_handle *handle); + +#endif /* FS_HANDLE_H */