Skip to content

Commit

Permalink
fixup! Fix dentry of open files after rename
Browse files Browse the repository at this point in the history
Signed-off-by: g2flyer <[email protected]>
  • Loading branch information
g2flyer committed Jun 12, 2024
1 parent 70307d4 commit 3f15945
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 6 deletions.
3 changes: 3 additions & 0 deletions libos/include/libos_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ struct libos_handle {
refcount_t ref_count;

struct libos_fs* fs;
/* dentry can change due to rename, so to secure read-access, aquire g_dcache_lock and/or
* handle->lock; to protect updates (unless during creation and deletion where unique use is
* guaranteed), acquire first g_dcache_lock and then handle-Lock */
struct libos_dentry* dentry;

/*
Expand Down
20 changes: 14 additions & 6 deletions libos/src/bookkeep/libos_handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ static int clear_posix_locks(struct libos_handle* handle) {
.end = FS_LOCK_EOF,
.pid = g_process.pid,
};
lock(&handle->lock);
int ret = file_lock_set(handle->dentry, &file_lock, /*block=*/false);
unlock(&handle->lock);
if (ret < 0) {
log_warning("error releasing locks: %s", unix_strerror(ret));
return ret;
Expand Down Expand Up @@ -477,13 +479,17 @@ int set_new_fd_handle_above_fd(uint32_t fd, struct libos_handle* hdl, int fd_fla
}

static inline __attribute__((unused)) const char* __handle_name(struct libos_handle* hdl) {
/* This function seems unused, so probably could be dropped? */
const char* ret = "(unknown)";
lock(&hdl->lock);
if (hdl->uri)
return hdl->uri;
ret = hdl->uri;
if (hdl->dentry && hdl->dentry->name[0] != '\0')
return hdl->dentry->name;
ret = hdl->dentry->name;
if (hdl->fs)
return hdl->fs->name;
return "(unknown)";
ret = hdl->fs->name;
unlock(&hdl->lock);
return ret;
}

void get_handle(struct libos_handle* hdl) {
Expand All @@ -499,6 +505,8 @@ static void destroy_handle(struct libos_handle* hdl) {

static int clear_flock_locks(struct libos_handle* hdl) {
/* Clear flock (BSD) locks for a file. We are required to do that when the handle is closed. */
int ret = 0;
lock(&hdl->lock);
if (hdl && hdl->dentry && hdl->created_by_process) {
assert(hdl->ref_count == 0);
struct libos_file_lock file_lock = {
Expand All @@ -509,10 +517,10 @@ static int clear_flock_locks(struct libos_handle* hdl) {
int ret = file_lock_set(hdl->dentry, &file_lock, /*block=*/false);
if (ret < 0) {
log_warning("error releasing locks: %s", unix_strerror(ret));
return ret;
}
}
return 0;
unlock(&hdl->lock);
return ret;
}

void put_handle(struct libos_handle* hdl) {
Expand Down
2 changes: 2 additions & 0 deletions libos/src/fs/libos_namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,10 @@ int get_dirfd_dentry(int dirfd, struct libos_dentry** dir) {
return -ENOTDIR;
}

lock(&hdl->lock); /* while hdl->is_dir is immutable, hdl->dentry can change due to rename */
get_dentry(hdl->dentry);
*dir = hdl->dentry;
unlock(&hdl->lock);
put_handle(hdl);
return 0;
}
1 change: 1 addition & 0 deletions libos/src/sys/libos_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ static int do_rename(struct libos_dentry* old_dent, struct libos_dentry* new_den
struct libos_handle* handle = fd_handle->handle;
/* TODO (MST): systematically go through all for other uses of handle->dentry as they also
* would require locking */
assert(locked(&g_dcache_lock));
lock(&handle->lock);
if ((handle->dentry == old_dent) && (handle->inode == new_dent->inode)) {
handle->dentry = new_dent;
Expand Down

0 comments on commit 3f15945

Please sign in to comment.