X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ffd-tracker%2Ffd-tracker.c;h=88f53c7418be7518c98cea62007fe3eb50f6bcea;hp=5e6c8f30ed64e4999990351bf383361aac93e15f;hb=f7c3ffd79ddcece895eb0de616001d549aced5fc;hpb=b13a2b17db29cbc8808e8bb149de1692b94729d3 diff --git a/src/common/fd-tracker/fd-tracker.c b/src/common/fd-tracker/fd-tracker.c index 5e6c8f30e..88f53c741 100644 --- a/src/common/fd-tracker/fd-tracker.c +++ b/src/common/fd-tracker/fd-tracker.c @@ -26,11 +26,13 @@ #include #include -#include "common/defaults.h" -#include "common/error.h" -#include "common/hashtable/hashtable.h" -#include "common/hashtable/utils.h" -#include "common/macros.h" +#include +#include +#include +#include +#include +#include +#include #include "fd-tracker.h" #include "inode.h" @@ -83,18 +85,18 @@ struct fd_tracker { struct cds_list_head suspended_handles; struct cds_lfht *unsuspendable_fds; struct lttng_inode_registry *inode_registry; + /* Unlinked files are moved in this directory under a unique name. */ + struct lttng_directory_handle *unlink_directory_handle; + struct lttng_unlinked_file_pool *unlinked_file_pool; }; struct open_properties { int flags; - struct { - bool is_set; - mode_t value; - } mode; + LTTNG_OPTIONAL(mode_t) mode; }; /* - * A fs_handle is not ref-counted. Therefore, it is assumed that a + * A fs_handle_tracked is not ref-counted. Therefore, it is assumed that a * handle is never in-use while it is being reclaimed. It can be * shared by multiple threads, but external synchronization is required * to ensure it is not still being used when it is reclaimed (close method). @@ -102,7 +104,8 @@ struct open_properties { * * The fs_handle lock always nests _within_ the tracker's lock. */ -struct fs_handle { +struct fs_handle_tracked { + struct fs_handle parent; pthread_mutex_t lock; /* * Weak reference to the tracker. All fs_handles are assumed to have @@ -143,21 +146,25 @@ static int match_fd(struct cds_lfht_node *node, const void *key); static void unsuspendable_fd_destroy(struct unsuspendable_fd *entry); static struct unsuspendable_fd *unsuspendable_fd_create( const char *name, int fd); -static int open_from_properties( +static int open_from_properties(const struct lttng_directory_handle *dir_handle, const char *path, struct open_properties *properties); -static void fs_handle_log(struct fs_handle *handle); -static int fs_handle_suspend(struct fs_handle *handle); -static int fs_handle_restore(struct fs_handle *handle); +static void fs_handle_tracked_log(struct fs_handle_tracked *handle); +static int fs_handle_tracked_suspend(struct fs_handle_tracked *handle); +static int fs_handle_tracked_restore(struct fs_handle_tracked *handle); +static int fs_handle_tracked_get_fd(struct fs_handle *_handle); +static void fs_handle_tracked_put_fd(struct fs_handle *_handle); +static int fs_handle_tracked_unlink(struct fs_handle *_handle); +static int fs_handle_tracked_close(struct fs_handle *_handle); static void fd_tracker_track( - struct fd_tracker *tracker, struct fs_handle *handle); + struct fd_tracker *tracker, struct fs_handle_tracked *handle); static void fd_tracker_untrack( - struct fd_tracker *tracker, struct fs_handle *handle); + struct fd_tracker *tracker, struct fs_handle_tracked *handle); static int fd_tracker_suspend_handles( struct fd_tracker *tracker, unsigned int count); static int fd_tracker_restore_handle( - struct fd_tracker *tracker, struct fs_handle *handle); + struct fd_tracker *tracker, struct fs_handle_tracked *handle); /* Match function of the tracker's unsuspendable_fds hash table. */ static int match_fd(struct cds_lfht_node *node, const void *key) @@ -208,12 +215,12 @@ error: return NULL; } -static void fs_handle_log(struct fs_handle *handle) +static void fs_handle_tracked_log(struct fs_handle_tracked *handle) { const char *path; pthread_mutex_lock(&handle->lock); - path = lttng_inode_get_path(handle->inode); + lttng_inode_get_location(handle->inode, NULL, &path); if (handle->fd >= 0) { DBG_NO_LOC(" %s [active, fd %d%s]", path, handle->fd, @@ -225,14 +232,15 @@ static void fs_handle_log(struct fs_handle *handle) } /* Tracker lock must be held by the caller. */ -static int fs_handle_suspend(struct fs_handle *handle) +static int fs_handle_tracked_suspend(struct fs_handle_tracked *handle) { int ret = 0; struct stat fs_stat; const char *path; + const struct lttng_directory_handle *node_directory_handle; pthread_mutex_lock(&handle->lock); - path = lttng_inode_get_path(handle->inode); + lttng_inode_get_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. */ @@ -240,7 +248,8 @@ static int fs_handle_suspend(struct fs_handle *handle) goto end; } - ret = stat(path, &fs_stat); + ret = lttng_directory_handle_stat( + node_directory_handle, path, &fs_stat); if (ret) { PERROR("Filesystem handle to %s cannot be suspended as stat() failed", path); @@ -283,14 +292,18 @@ end: } /* Caller must hold the tracker and handle's locks. */ -static int fs_handle_restore(struct fs_handle *handle) +static int fs_handle_tracked_restore(struct fs_handle_tracked *handle) { int ret, fd = -1; - const char *path = lttng_inode_get_path(handle->inode); + const char *path; + const struct lttng_directory_handle *node_directory_handle; + + lttng_inode_get_location(handle->inode, &node_directory_handle, &path); assert(handle->fd == -1); assert(path); - ret = open_from_properties(path, &handle->properties); + ret = open_from_properties( + node_directory_handle, path, &handle->properties); if (ret < 0) { PERROR("Failed to restore filesystem handle to %s, open() failed", path); @@ -318,7 +331,7 @@ end: return ret; } -static int open_from_properties( +static int open_from_properties(const struct lttng_directory_handle *dir_handle, const char *path, struct open_properties *properties) { int ret; @@ -330,9 +343,11 @@ static int open_from_properties( * thus it is ignored here. */ if ((properties->flags & O_CREAT) && properties->mode.is_set) { - ret = open(path, properties->flags, properties->mode.value); + ret = lttng_directory_handle_open_file(dir_handle, path, + properties->flags, properties->mode.value); } else { - ret = open(path, properties->flags); + ret = lttng_directory_handle_open_file(dir_handle, path, + properties->flags, 0); } /* * Some flags should not be used beyond the initial open() of a @@ -353,7 +368,8 @@ end: return ret; } -struct fd_tracker *fd_tracker_create(unsigned int capacity) +struct fd_tracker *fd_tracker_create(const char *unlinked_file_path, + unsigned int capacity) { struct fd_tracker *tracker = zmalloc(sizeof(struct fd_tracker)); @@ -382,6 +398,12 @@ struct fd_tracker *fd_tracker_create(unsigned int capacity) ERR("Failed to create fd-tracker's inode registry"); goto error; } + + tracker->unlinked_file_pool = + lttng_unlinked_file_pool_create(unlinked_file_path); + if (!tracker->unlinked_file_pool) { + goto error; + } DBG("File descriptor tracker created with a limit of %u simultaneously-opened FDs", capacity); end: @@ -393,7 +415,7 @@ error: void fd_tracker_log(struct fd_tracker *tracker) { - struct fs_handle *handle; + struct fs_handle_tracked *handle; struct unsuspendable_fd *unsuspendable_fd; struct cds_lfht_iter iter; @@ -411,13 +433,13 @@ void fd_tracker_log(struct fd_tracker *tracker) DBG_NO_LOC(" capacity: %u", tracker->capacity); DBG_NO_LOC(" Tracked suspendable file descriptors"); - cds_list_for_each_entry ( + cds_list_for_each_entry( handle, &tracker->active_handles, handles_list_node) { - fs_handle_log(handle); + fs_handle_tracked_log(handle); } - cds_list_for_each_entry (handle, &tracker->suspended_handles, + cds_list_for_each_entry(handle, &tracker->suspended_handles, handles_list_node) { - fs_handle_log(handle); + fs_handle_tracked_log(handle); } if (!SUSPENDABLE_COUNT(tracker)) { DBG_NO_LOC(" None"); @@ -425,7 +447,7 @@ void fd_tracker_log(struct fd_tracker *tracker) DBG_NO_LOC(" Tracked unsuspendable file descriptors"); rcu_read_lock(); - cds_lfht_for_each_entry (tracker->unsuspendable_fds, &iter, + cds_lfht_for_each_entry(tracker->unsuspendable_fds, &iter, unsuspendable_fd, tracker_node) { DBG_NO_LOC(" %s [active, fd %d]", unsuspendable_fd->name ?: "Unnamed", @@ -464,6 +486,7 @@ int fd_tracker_destroy(struct fd_tracker *tracker) } lttng_inode_registry_destroy(tracker->inode_registry); + lttng_unlinked_file_pool_destroy(tracker->unlinked_file_pool); pthread_mutex_destroy(&tracker->lock); free(tracker); end: @@ -471,12 +494,13 @@ end: } struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, + struct lttng_directory_handle *directory, const char *path, int flags, mode_t *mode) { int ret; - struct fs_handle *handle = NULL; + struct fs_handle_tracked *handle = NULL; struct stat fd_stat; struct open_properties properties = { .flags = flags, @@ -507,6 +531,13 @@ struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, if (!handle) { goto end; } + handle->parent = (typeof(handle->parent)) { + .get_fd = fs_handle_tracked_get_fd, + .put_fd = fs_handle_tracked_put_fd, + .unlink = fs_handle_tracked_unlink, + .close = fs_handle_tracked_close, + }; + handle->tracker = tracker; ret = pthread_mutex_init(&handle->lock, NULL); @@ -515,7 +546,7 @@ struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, goto error_mutex_init; } - handle->fd = open_from_properties(path, &properties); + handle->fd = open_from_properties(directory, path, &properties); if (handle->fd < 0) { PERROR("Failed to open fs handle to %s, open() returned", path); goto error; @@ -523,8 +554,9 @@ struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, handle->properties = properties; - handle->inode = lttng_inode_registry_get_inode( - tracker->inode_registry, handle->fd, path); + handle->inode = lttng_inode_registry_get_inode(tracker->inode_registry, + directory, path, handle->fd, + tracker->unlinked_file_pool); if (!handle->inode) { ERR("Failed to get lttng_inode corresponding to file %s", path); goto error; @@ -539,7 +571,7 @@ struct fs_handle *fd_tracker_open_fs_handle(struct fd_tracker *tracker, fd_tracker_track(tracker, handle); end: pthread_mutex_unlock(&tracker->lock); - return handle; + return handle ? &handle->parent : NULL; error: if (handle->inode) { lttng_inode_put(handle->inode); @@ -556,20 +588,22 @@ static int fd_tracker_suspend_handles( struct fd_tracker *tracker, unsigned int count) { unsigned int left_to_close = count; - struct fs_handle *handle, *tmp; + unsigned int attempts_left = tracker->count.suspendable.active; + struct fs_handle_tracked *handle, *tmp; - cds_list_for_each_entry_safe (handle, tmp, &tracker->active_handles, + cds_list_for_each_entry_safe(handle, tmp, &tracker->active_handles, handles_list_node) { int ret; fd_tracker_untrack(tracker, handle); - ret = fs_handle_suspend(handle); + ret = fs_handle_tracked_suspend(handle); fd_tracker_track(tracker, handle); if (!ret) { left_to_close--; } + attempts_left--; - if (!left_to_close) { + if (left_to_close == 0 || attempts_left == 0) { break; } } @@ -742,7 +776,7 @@ end: /* Caller must have taken the tracker's and handle's locks. */ static void fd_tracker_track( - struct fd_tracker *tracker, struct fs_handle *handle) + struct fd_tracker *tracker, struct fs_handle_tracked *handle) { if (handle->fd >= 0) { tracker->count.suspendable.active++; @@ -757,7 +791,7 @@ static void fd_tracker_track( /* Caller must have taken the tracker's and handle's locks. */ static void fd_tracker_untrack( - struct fd_tracker *tracker, struct fs_handle *handle) + struct fd_tracker *tracker, struct fs_handle_tracked *handle) { if (handle->fd >= 0) { tracker->count.suspendable.active--; @@ -769,7 +803,7 @@ static void fd_tracker_untrack( /* Caller must have taken the tracker's and handle's locks. */ static int fd_tracker_restore_handle( - struct fd_tracker *tracker, struct fs_handle *handle) + struct fd_tracker *tracker, struct fs_handle_tracked *handle) { int ret; @@ -780,15 +814,17 @@ static int fd_tracker_restore_handle( goto end; } } - ret = fs_handle_restore(handle); + ret = fs_handle_tracked_restore(handle); end: fd_tracker_track(tracker, handle); return ret ? ret : handle->fd; } -int fs_handle_get_fd(struct fs_handle *handle) +static int fs_handle_tracked_get_fd(struct fs_handle *_handle) { int ret; + struct fs_handle_tracked *handle = + container_of(_handle, struct fs_handle_tracked, parent); /* * TODO This should be optimized as it is a fairly hot path. @@ -826,29 +862,36 @@ end: return ret; } -void fs_handle_put_fd(struct fs_handle *handle) +static void fs_handle_tracked_put_fd(struct fs_handle *_handle) { + struct fs_handle_tracked *handle = + container_of(_handle, struct fs_handle_tracked, parent); + pthread_mutex_lock(&handle->lock); handle->in_use = false; pthread_mutex_unlock(&handle->lock); } -int fs_handle_unlink(struct fs_handle *handle) +static int fs_handle_tracked_unlink(struct fs_handle *_handle) { int ret; + struct fs_handle_tracked *handle = + container_of(_handle, struct fs_handle_tracked, parent); pthread_mutex_lock(&handle->tracker->lock); pthread_mutex_lock(&handle->lock); - ret = lttng_inode_defer_unlink(handle->inode); + ret = lttng_inode_unlink(handle->inode); pthread_mutex_unlock(&handle->lock); pthread_mutex_unlock(&handle->tracker->lock); return ret; } -int fs_handle_close(struct fs_handle *handle) +static int fs_handle_tracked_close(struct fs_handle *_handle) { int ret = 0; const char *path = NULL; + struct fs_handle_tracked *handle = + container_of(_handle, struct fs_handle_tracked, parent); if (!handle) { ret = -EINVAL; @@ -858,7 +901,7 @@ int fs_handle_close(struct fs_handle *handle) pthread_mutex_lock(&handle->tracker->lock); pthread_mutex_lock(&handle->lock); if (handle->inode) { - path = lttng_inode_get_path(handle->inode); + lttng_inode_get_location(handle->inode, NULL, &path); } fd_tracker_untrack(handle->tracker, handle); if (handle->fd >= 0) {