#include "common/hashtable/hashtable.h"
#include "fd-tracker.h"
+#include "inode.h"
/* Tracker lock must be taken by the user. */
#define TRACKED_COUNT(tracker) \
struct cds_list_head active_handles;
struct cds_list_head suspended_handles;
struct cds_lfht *unsuspendable_fds;
+ struct lttng_inode_registry *inode_registry;
};
struct open_properties {
- char *path;
int flags;
struct {
bool is_set;
*/
struct fd_tracker *tracker;
struct open_properties properties;
+ struct lttng_inode *inode;
int fd;
/* inode number of the file at the time of the handle's creation. */
uint64_t ino;
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(struct open_properties *properties);
+static int open_from_properties(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
void fs_handle_log(struct fs_handle *handle)
{
+ const char *path;
+
pthread_mutex_lock(&handle->lock);
+ path = lttng_inode_get_path(handle->inode);
+
if (handle->fd >= 0) {
DBG_NO_LOC(" %s [active, fd %d%s]",
- handle->properties.path,
+ path,
handle->fd,
handle->in_use ? ", in use" : "");
} else {
- DBG_NO_LOC(" %s [suspended]", handle->properties.path);
+ DBG_NO_LOC(" %s [suspended]", path);
}
pthread_mutex_unlock(&handle->lock);
}
+/* Tracker lock must be held by the caller. */
static
int fs_handle_suspend(struct fs_handle *handle)
{
int ret = 0;
struct stat fs_stat;
+ const char *path;
pthread_mutex_lock(&handle->lock);
+ path = lttng_inode_get_path(handle->inode);
assert(handle->fd >= 0);
if (handle->in_use) {
/* This handle can't be suspended as it is currently in use. */
goto end;
}
- ret = stat(handle->properties.path, &fs_stat);
+ ret = stat(path, &fs_stat);
if (ret) {
PERROR("Filesystem handle to %s cannot be suspended as stat() failed",
- handle->properties.path);
+ path);
ret = -errno;
goto end;
}
if (fs_stat.st_ino != handle->ino) {
/* Don't suspend as the handle would not be restorable. */
WARN("Filesystem handle to %s cannot be suspended as its inode changed",
- handle->properties.path);
+ path);
ret = -ENOENT;
goto end;
}
handle->offset = lseek(handle->fd, 0, SEEK_CUR);
if (handle->offset == -1) {
WARN("Filesystem handle to %s cannot be suspended as lseek() failed to sample its current position",
- handle->properties.path);
+ path);
ret = -errno;
goto end;
}
ret = close(handle->fd);
if (ret) {
PERROR("Filesystem handle to %s cannot be suspended as close() failed",
- handle->properties.path);
+ path);
ret = -errno;
goto end;
}
DBG("Suspended filesystem handle to %s (fd %i) at position %" PRId64,
- handle->properties.path, handle->fd, handle->offset);
+ path, handle->fd, handle->offset);
handle->fd = -1;
end:
if (ret) {
int fs_handle_restore(struct fs_handle *handle)
{
int ret, fd = -1;
+ const char *path = lttng_inode_get_path(handle->inode);
assert(handle->fd == -1);
- ret = open_from_properties(&handle->properties);
+ assert(path);
+ ret = open_from_properties(path,
+ &handle->properties);
if (ret < 0) {
PERROR("Failed to restore filesystem handle to %s, open() failed",
- handle->properties.path);
+ path);
ret = -errno;
goto end;
}
ret = lseek(fd, handle->offset, SEEK_SET);
if (ret < 0) {
PERROR("Failed to restore filesystem handle to %s, lseek() failed",
- handle->properties.path);
+ path);
ret = -errno;
goto end;
}
DBG("Restored filesystem handle to %s (fd %i) at position %" PRId64,
- handle->properties.path, fd, handle->offset);
+ path, fd, handle->offset);
ret = 0;
handle->fd = fd;
fd = -1;
}
static
-int open_from_properties(struct open_properties *properties)
+int open_from_properties(const char *path, struct open_properties *properties)
{
int ret;
* thus it is ignored here.
*/
if ((properties->flags & O_CREAT) && properties->mode.is_set) {
- ret = open(properties->path, properties->flags,
+ ret = open(path, properties->flags,
properties->mode.value);
} else {
- ret = open(properties->path, properties->flags);
+ ret = open(path, properties->flags);
}
/*
* Some flags should not be used beyond the initial open() of a
tracker->capacity = capacity;
tracker->unsuspendable_fds = cds_lfht_new(DEFAULT_HT_SIZE, 1, 0,
CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
+ if (!tracker->unsuspendable_fds) {
+ ERR("Failed to create fd-tracker's unsuspendable_fds hash table");
+ goto error;
+ }
+ tracker->inode_registry = lttng_inode_registry_create();
+ if (!tracker->inode_registry) {
+ ERR("Failed to create fd-tracker's inode registry");
+ goto error;
+ }
DBG("File descriptor tracker created with a limit of %u simultaneously-opened FDs",
capacity);
end:
return tracker;
+error:
+ fd_tracker_destroy(tracker);
+ return NULL;
}
void fd_tracker_log(struct fd_tracker *tracker)
}
pthread_mutex_unlock(&tracker->lock);
- ret = cds_lfht_destroy(tracker->unsuspendable_fds, NULL);
- assert(!ret);
+ if (tracker->unsuspendable_fds) {
+ ret = cds_lfht_destroy(tracker->unsuspendable_fds, NULL);
+ assert(!ret);
+ }
pthread_mutex_destroy(&tracker->lock);
free(tracker);
end:
struct fs_handle *handle = NULL;
struct stat fd_stat;
struct open_properties properties = {
- .path = strdup(path),
.flags = flags,
.mode.is_set = !!mode,
.mode.value = mode ? *mode : 0,
};
- if (!properties.path) {
- goto end;
- }
-
pthread_mutex_lock(&tracker->lock);
if (ACTIVE_COUNT(tracker) == tracker->capacity) {
if (tracker->count.suspendable.active > 0) {
goto end;
}
- handle->fd = open_from_properties(&properties);
+ handle->fd = open_from_properties(path, &properties);
if (handle->fd < 0) {
PERROR("Failed to open fs handle to %s, open() returned", path);
ret = -errno;
}
handle->properties = properties;
- properties.path = NULL;
+
+ handle->inode = lttng_inode_registry_get_inode(tracker->inode_registry,
+ handle->fd, path);
+ if (!handle->inode) {
+ ERR("Failed to get lttng_inode corresponding to file %s",
+ path);
+ goto error_destroy;
+ }
if (fstat(handle->fd, &fd_stat)) {
PERROR("Failed to retrieve file descriptor inode while creating fs handle, fstat() returned");
handle->tracker = tracker;
pthread_mutex_unlock(&tracker->lock);
end:
- free(properties.path);
return handle;
error_destroy:
pthread_mutex_unlock(&tracker->lock);
int fs_handle_close(struct fs_handle *handle)
{
int ret = 0;
+ const char *path;
if (!handle) {
ret = -EINVAL;
pthread_mutex_lock(&handle->tracker->lock);
pthread_mutex_lock(&handle->lock);
+ path = lttng_inode_get_path(handle->inode);
fd_tracker_untrack(handle->tracker, handle);
if (handle->fd >= 0) {
/*
*/
if (close(handle->fd)) {
PERROR("Failed to close the file descritptor (%d) of fs handle to %s, close() returned",
- handle->fd, handle->properties.path);
+ handle->fd, path);
}
handle->fd = -1;
}
+ lttng_inode_put(handle->inode);
pthread_mutex_unlock(&handle->lock);
pthread_mutex_destroy(&handle->lock);
pthread_mutex_unlock(&handle->tracker->lock);
- free(handle->properties.path);
free(handle);
end:
return ret;