mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-01-20 01:32:54 +08:00
fix for unlink race condition
This commit is contained in:
parent
060cae6270
commit
61cded5b34
|
@ -129,7 +129,7 @@ struct fuse_operations {
|
||||||
* while open. Helps manage the fact the kernel usually does
|
* while open. Helps manage the fact the kernel usually does
|
||||||
* not send fh with getattr requests.
|
* 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_);
|
int (*free_hide)(const uint64_t fh_);
|
||||||
|
|
||||||
/** Remove a file */
|
/** Remove a file */
|
||||||
|
@ -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_init(struct fuse_fs *fs, struct fuse_conn_info *conn);
|
||||||
void fuse_fs_destroy(struct fuse_fs *fs);
|
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);
|
int fuse_notify_poll(struct fuse_pollhandle *ph);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -438,11 +438,18 @@ static void set_forget_time(struct fuse *f, struct node *node)
|
||||||
curr_time(&lnode->forget_time);
|
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)
|
if(node_->name != node_->inline_name)
|
||||||
free(node->name);
|
free(node_->name);
|
||||||
free_node_mem(f, node);
|
|
||||||
|
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)
|
static void node_table_reduce(struct node_table *t)
|
||||||
|
@ -1529,13 +1536,12 @@ fuse_fs_rename(struct fuse_fs *fs,
|
||||||
int
|
int
|
||||||
fuse_fs_prepare_hide(struct fuse_fs *fs_,
|
fuse_fs_prepare_hide(struct fuse_fs *fs_,
|
||||||
const char *path_,
|
const char *path_,
|
||||||
uint64_t *fh_,
|
uint64_t *fh_)
|
||||||
int type_)
|
|
||||||
{
|
{
|
||||||
fuse_get_context()->private_data = fs_->user_data;
|
fuse_get_context()->private_data = fs_->user_data;
|
||||||
|
|
||||||
if(fs_->op.prepare_hide)
|
if(fs_->op.prepare_hide)
|
||||||
return fs_->op.prepare_hide(path_,fh_,type_);
|
return fs_->op.prepare_hide(path_,fh_);
|
||||||
|
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
@ -2303,11 +2309,10 @@ int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
node_open_and_visible(const struct node *node_)
|
node_open(const struct node *node_)
|
||||||
{
|
{
|
||||||
return ((node_ != NULL) &&
|
return ((node_ != NULL) &&
|
||||||
(node_->open_count > 0) &&
|
(node_->open_count > 0));
|
||||||
(node_->is_hidden == 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
|
static int mtime_eq(const struct stat *stbuf, const struct timespec *ts)
|
||||||
|
@ -2906,15 +2911,18 @@ fuse_lib_unlink(fuse_req_t req,
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
fuse_prepare_interrupt(f,req,&d);
|
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)
|
if(!err)
|
||||||
wnode->is_hidden = 1;
|
wnode->is_hidden = 1;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
|
||||||
err = fuse_fs_unlink(f->fs,path);
|
err = fuse_fs_unlink(f->fs,path);
|
||||||
if(!err && !wnode->is_hidden)
|
if(!err)
|
||||||
remove_node(f,parent,name);
|
remove_node(f,parent,name);
|
||||||
|
|
||||||
fuse_finish_interrupt(f,req,&d);
|
fuse_finish_interrupt(f,req,&d);
|
||||||
|
@ -2990,12 +2998,15 @@ fuse_lib_rename(fuse_req_t req,
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
fuse_prepare_interrupt(f,req,&d);
|
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)
|
if(!err)
|
||||||
wnode2->is_hidden = 1;
|
wnode2->is_hidden = 1;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&f->lock);
|
||||||
|
|
||||||
err = fuse_fs_rename(f->fs,oldpath,newpath);
|
err = fuse_fs_rename(f->fs,oldpath,newpath);
|
||||||
if(!err)
|
if(!err)
|
||||||
|
|
|
@ -26,8 +26,7 @@ namespace FUSE
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
prepare_hide(const char *fusepath_,
|
prepare_hide(const char *fusepath_,
|
||||||
uint64_t *fh_,
|
uint64_t *fh_)
|
||||||
int type_)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct fuse_file_info ffi = {0};
|
struct fuse_file_info ffi = {0};
|
||||||
|
|
|
@ -24,6 +24,5 @@ namespace FUSE
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
prepare_hide(const char *name_,
|
prepare_hide(const char *name_,
|
||||||
uint64_t *fh_,
|
uint64_t *fh_);
|
||||||
int type_);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user