X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ffd-tracker%2Ffd-tracker.c;h=772bf04bc5994efa5fc351a2ed933514506de36c;hp=417859abe889e0e8b94eabe88dd9fd0d00376f9c;hb=ea05fafd4088958df7f994fcf903627bc609808d;hpb=ab5be9fa2eb5ba9600a82cd18fd3cfcbac69169a diff --git a/src/common/fd-tracker/fd-tracker.c b/src/common/fd-tracker/fd-tracker.c index 417859abe..772bf04bc 100644 --- a/src/common/fd-tracker/fd-tracker.c +++ b/src/common/fd-tracker/fd-tracker.c @@ -210,7 +210,7 @@ static void fs_handle_tracked_log(struct fs_handle_tracked *handle) const char *path; pthread_mutex_lock(&handle->lock); - lttng_inode_get_location(handle->inode, NULL, &path); + lttng_inode_borrow_location(handle->inode, NULL, &path); if (handle->fd >= 0) { DBG_NO_LOC(" %s [active, fd %d%s]", path, handle->fd, @@ -230,7 +230,8 @@ static int fs_handle_tracked_suspend(struct fs_handle_tracked *handle) const struct lttng_directory_handle *node_directory_handle; pthread_mutex_lock(&handle->lock); - lttng_inode_get_location(handle->inode, &node_directory_handle, &path); + lttng_inode_borrow_location( + handle->inode, &node_directory_handle, &path); assert(handle->fd >= 0); if (handle->in_use) { /* This handle can't be suspended as it is currently in use. */ @@ -288,7 +289,8 @@ static int fs_handle_tracked_restore(struct fs_handle_tracked *handle) const char *path; const struct lttng_directory_handle *node_directory_handle; - lttng_inode_get_location(handle->inode, &node_directory_handle, &path); + lttng_inode_borrow_location( + handle->inode, &node_directory_handle, &path); assert(handle->fd == -1); assert(path); @@ -358,6 +360,7 @@ end: return ret; } +LTTNG_HIDDEN struct fd_tracker *fd_tracker_create(const char *unlinked_file_path, unsigned int capacity) { @@ -403,6 +406,7 @@ error: return NULL; } +LTTNG_HIDDEN void fd_tracker_log(struct fd_tracker *tracker) { struct fs_handle_tracked *handle; @@ -451,10 +455,14 @@ void fd_tracker_log(struct fd_tracker *tracker) pthread_mutex_unlock(&tracker->lock); } +LTTNG_HIDDEN int fd_tracker_destroy(struct fd_tracker *tracker) { int ret = 0; + if (!tracker) { + goto end; + } /* * Refuse to destroy the tracker as fs_handles may still old * weak references to the tracker. @@ -483,6 +491,7 @@ end: return ret; } +LTTNG_HIDDEN struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, struct lttng_directory_handle *directory, const char *path, @@ -600,6 +609,7 @@ static int fd_tracker_suspend_handles( return left_to_close ? -EMFILE : 0; } +LTTNG_HIDDEN int fd_tracker_open_unsuspendable_fd(struct fd_tracker *tracker, int *out_fds, const char **names, @@ -632,7 +642,7 @@ int fd_tracker_open_unsuspendable_fd(struct fd_tracker *tracker, } else { /* * There are not enough active suspendable file - * descriptors to open a new fd and still accomodate the + * descriptors to open a new fd and still accommodates the * tracker's capacity. */ WARN("Cannot open unsuspendable fd, too many unsuspendable file descriptors are opened (%u)", @@ -697,6 +707,7 @@ end_free_entries: goto end_unlock; } +LTTNG_HIDDEN int fd_tracker_close_unsuspendable_fd(struct fd_tracker *tracker, int *fds_in, unsigned int fd_count, @@ -882,6 +893,7 @@ static int fs_handle_tracked_close(struct fs_handle *_handle) const char *path = NULL; struct fs_handle_tracked *handle = container_of(_handle, struct fs_handle_tracked, parent); + struct lttng_directory_handle *inode_directory_handle = NULL; if (!handle) { ret = -EINVAL; @@ -891,7 +903,29 @@ static int fs_handle_tracked_close(struct fs_handle *_handle) pthread_mutex_lock(&handle->tracker->lock); pthread_mutex_lock(&handle->lock); if (handle->inode) { - lttng_inode_get_location(handle->inode, NULL, &path); + lttng_inode_borrow_location(handle->inode, NULL, &path); + /* + * Here a reference to the inode's directory handle is acquired + * to prevent the last reference to it from being released while + * the tracker's lock is taken. + * + * If this wasn't done, the directory handle could attempt to + * close its underlying directory file descriptor, which would + * attempt to lock the tracker's lock, resulting in a deadlock. + * + * Since a new reference to the directory handle is taken within + * the scope of this function, it is not possible for the last + * reference to the inode's location directory handle to be + * released during the call to lttng_inode_put(). + * + * We wait until the tracker's lock is released to release the + * reference. Hence, the call to the tracker is delayed just + * enough to not attempt to recursively acquire the tracker's + * lock twice. + */ + inode_directory_handle = + lttng_inode_get_location_directory_handle( + handle->inode); } fd_tracker_untrack(handle->tracker, handle); if (handle->fd >= 0) { @@ -900,7 +934,7 @@ static int fs_handle_tracked_close(struct fs_handle *_handle) * isn't much the user can do about it. */ if (close(handle->fd)) { - PERROR("Failed to close the file descritptor (%d) of fs handle to %s, close() returned", + PERROR("Failed to close the file descriptor (%d) of fs handle to %s, close() returned", handle->fd, path ? path : "Unknown"); } handle->fd = -1; @@ -912,6 +946,7 @@ static int fs_handle_tracked_close(struct fs_handle *_handle) pthread_mutex_destroy(&handle->lock); pthread_mutex_unlock(&handle->tracker->lock); free(handle); + lttng_directory_handle_put(inode_directory_handle); end: return ret; }