Skip to content

Commit

Permalink
Merge pull request #628 from trapexit/hide-cleanup
Browse files Browse the repository at this point in the history
fix for unlink race condition
  • Loading branch information
trapexit authored May 22, 2019
2 parents 060cae6 + 61cded5 commit 9e3331d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
5 changes: 4 additions & 1 deletion libfuse/include/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ struct fuse_operations {
* while open. Helps manage the fact the kernel usually does
* not send fh with getattr requests.
*/
int (*prepare_hide)(const char *name_, uint64_t *fh_, int type_);
int (*prepare_hide)(const char *name_, uint64_t *fh_);
int (*free_hide)(const uint64_t fh_);

/** Remove a file */
Expand Down Expand Up @@ -921,6 +921,9 @@ int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn);
void fuse_fs_destroy(struct fuse_fs *fs);

int fuse_fs_prepare_hide(struct fuse_fs *fs, const char *path, uint64_t *fh);
int fuse_fs_free_hide(struct fuse_fs *fs, uint64_t fh);

int fuse_notify_poll(struct fuse_pollhandle *ph);

/**
Expand Down
43 changes: 27 additions & 16 deletions libfuse/lib/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,11 +438,18 @@ static void set_forget_time(struct fuse *f, struct node *node)
curr_time(&lnode->forget_time);
}

static void free_node(struct fuse *f, struct node *node)
static
void
free_node(struct fuse *f_,
struct node *node_)
{
if (node->name != node->inline_name)
free(node->name);
free_node_mem(f, node);
if(node_->name != node_->inline_name)
free(node_->name);

if(node_->is_hidden)
fuse_fs_free_hide(f_->fs,node_->hidden_fh);

free_node_mem(f_,node_);
}

static void node_table_reduce(struct node_table *t)
Expand Down Expand Up @@ -1529,13 +1536,12 @@ fuse_fs_rename(struct fuse_fs *fs,
int
fuse_fs_prepare_hide(struct fuse_fs *fs_,
const char *path_,
uint64_t *fh_,
int type_)
uint64_t *fh_)
{
fuse_get_context()->private_data = fs_->user_data;

if(fs_->op.prepare_hide)
return fs_->op.prepare_hide(path_,fh_,type_);
return fs_->op.prepare_hide(path_,fh_);

return -ENOSYS;
}
Expand Down Expand Up @@ -2303,11 +2309,10 @@ int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,

static
int
node_open_and_visible(const struct node *node_)
node_open(const struct node *node_)
{
return ((node_ != NULL) &&
(node_->open_count > 0) &&
(node_->is_hidden == 0));
return ((node_ != NULL) &&
(node_->open_count > 0));
}

static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
Expand Down Expand Up @@ -2906,15 +2911,18 @@ fuse_lib_unlink(fuse_req_t req,
if(!err)
{
fuse_prepare_interrupt(f,req,&d);
if(node_open_and_visible(wnode))

pthread_mutex_lock(&f->lock);
if(node_open(wnode))
{
err = fuse_fs_prepare_hide(f->fs,path,&wnode->hidden_fh,0);
err = fuse_fs_prepare_hide(f->fs,path,&wnode->hidden_fh);
if(!err)
wnode->is_hidden = 1;
}
pthread_mutex_unlock(&f->lock);

err = fuse_fs_unlink(f->fs,path);
if(!err && !wnode->is_hidden)
if(!err)
remove_node(f,parent,name);

fuse_finish_interrupt(f,req,&d);
Expand Down Expand Up @@ -2990,12 +2998,15 @@ fuse_lib_rename(fuse_req_t req,
if(!err)
{
fuse_prepare_interrupt(f,req,&d);
if(node_open_and_visible(wnode2))

pthread_mutex_lock(&f->lock);
if(node_open(wnode2))
{
err = fuse_fs_prepare_hide(f->fs,newpath,&wnode2->hidden_fh,1);
err = fuse_fs_prepare_hide(f->fs,newpath,&wnode2->hidden_fh);
if(!err)
wnode2->is_hidden = 1;
}
pthread_mutex_unlock(&f->lock);

err = fuse_fs_rename(f->fs,oldpath,newpath);
if(!err)
Expand Down
3 changes: 1 addition & 2 deletions src/fuse_prepare_hide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ namespace FUSE
{
int
prepare_hide(const char *fusepath_,
uint64_t *fh_,
int type_)
uint64_t *fh_)
{
int rv;
struct fuse_file_info ffi = {0};
Expand Down
3 changes: 1 addition & 2 deletions src/fuse_prepare_hide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@ namespace FUSE
{
int
prepare_hide(const char *name_,
uint64_t *fh_,
int type_);
uint64_t *fh_);
}

0 comments on commit 9e3331d

Please sign in to comment.