X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ffd-tracker%2Ffd-tracker.c;h=188abfb6d2792f4f3f2eb9d899e6fb62d784f522;hp=88f53c7418be7518c98cea62007fe3eb50f6bcea;hb=dd95933f8371a8c81ffc1dc5b306f2263f1ff808;hpb=f7c3ffd79ddcece895eb0de616001d549aced5fc diff --git a/src/common/fd-tracker/fd-tracker.c b/src/common/fd-tracker/fd-tracker.c index 88f53c741..188abfb6d 100644 --- a/src/common/fd-tracker/fd-tracker.c +++ b/src/common/fd-tracker/fd-tracker.c @@ -1,18 +1,8 @@ /* - * Copyright (C) 2018, 2020 - Jérémie Galarneau + * Copyright (C) 2018-2020 Jérémie Galarneau * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -220,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, @@ -240,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. */ @@ -298,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); @@ -892,6 +884,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; @@ -901,7 +894,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) { @@ -922,6 +937,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; }