mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-03-14 09:55:12 +08:00
add ctime support
This commit is contained in:
parent
e6c8fa3fad
commit
4b9f3de814
@ -128,16 +128,6 @@ struct fuse_forget_data {
|
||||
uint64_t nlookup;
|
||||
};
|
||||
|
||||
/* 'to_set' flags in setattr */
|
||||
#define FUSE_SET_ATTR_MODE (1 << 0)
|
||||
#define FUSE_SET_ATTR_UID (1 << 1)
|
||||
#define FUSE_SET_ATTR_GID (1 << 2)
|
||||
#define FUSE_SET_ATTR_SIZE (1 << 3)
|
||||
#define FUSE_SET_ATTR_ATIME (1 << 4)
|
||||
#define FUSE_SET_ATTR_MTIME (1 << 5)
|
||||
#define FUSE_SET_ATTR_ATIME_NOW (1 << 7)
|
||||
#define FUSE_SET_ATTR_MTIME_NOW (1 << 8)
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Request methods and replies *
|
||||
* ----------------------------------------------------------- */
|
||||
|
@ -2735,120 +2735,126 @@ fuse_fs_fchmod(struct fuse_fs *fs_,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
|
||||
int valid, struct fuse_file_info *fi)
|
||||
static
|
||||
void
|
||||
fuse_lib_setattr(fuse_req_t req,
|
||||
fuse_ino_t ino,
|
||||
struct stat *attr,
|
||||
int valid,
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
struct fuse *f = req_fuse_prepare(req);
|
||||
struct stat buf;
|
||||
char *path;
|
||||
int err;
|
||||
struct node *node;
|
||||
struct fuse_file_info ffi = {0};
|
||||
struct fuse *f = req_fuse_prepare(req);
|
||||
struct stat buf;
|
||||
char *path;
|
||||
int err;
|
||||
struct node *node;
|
||||
struct fuse_file_info ffi = {0};
|
||||
|
||||
if(fi == NULL)
|
||||
if(fi == NULL)
|
||||
{
|
||||
pthread_mutex_lock(&f->lock);
|
||||
node = get_node(f,ino);
|
||||
if(node->is_hidden)
|
||||
{
|
||||
fi = &ffi;
|
||||
fi->fh = node->hidden_fh;
|
||||
}
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
}
|
||||
|
||||
memset(&buf,0,sizeof(buf));
|
||||
|
||||
path = NULL;
|
||||
err = ((fi == NULL) ?
|
||||
get_path(f,ino,&path) :
|
||||
get_path_nullok(f,ino,&path));
|
||||
|
||||
if(!err)
|
||||
{
|
||||
struct fuse_intr_data d;
|
||||
|
||||
fuse_prepare_interrupt(f,req,&d);
|
||||
|
||||
err = 0;
|
||||
if (!err && (valid & FATTR_MODE))
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_chmod(f->fs,path,attr->st_mode) :
|
||||
fuse_fs_fchmod(f->fs,fi,attr->st_mode));
|
||||
|
||||
if(!err && (valid & (FATTR_UID | FATTR_GID)))
|
||||
{
|
||||
uid_t uid = ((valid & FATTR_UID) ? attr->st_uid : (uid_t) -1);
|
||||
gid_t gid = ((valid & FATTR_GID) ? attr->st_gid : (gid_t) -1);
|
||||
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_chown(f->fs,path,uid,gid) :
|
||||
fuse_fs_fchown(f->fs,fi,uid,gid));
|
||||
}
|
||||
|
||||
if(!err && (valid & FATTR_SIZE))
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_truncate(f->fs,path,attr->st_size) :
|
||||
fuse_fs_ftruncate(f->fs,path,attr->st_size,fi));
|
||||
|
||||
#ifdef HAVE_UTIMENSAT
|
||||
if(!err && f->utime_omit_ok && (valid & (FATTR_ATIME | FATTR_MTIME)))
|
||||
{
|
||||
struct timespec tv[2];
|
||||
|
||||
tv[0].tv_sec = 0;
|
||||
tv[1].tv_sec = 0;
|
||||
tv[0].tv_nsec = UTIME_OMIT;
|
||||
tv[1].tv_nsec = UTIME_OMIT;
|
||||
|
||||
if(valid & FATTR_ATIME_NOW)
|
||||
tv[0].tv_nsec = UTIME_NOW;
|
||||
else if(valid & FATTR_ATIME)
|
||||
tv[0] = attr->st_atim;
|
||||
|
||||
if(valid & FATTR_MTIME_NOW)
|
||||
tv[1].tv_nsec = UTIME_NOW;
|
||||
else if(valid & FATTR_MTIME)
|
||||
tv[1] = attr->st_mtim;
|
||||
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_utimens(f->fs,path,tv) :
|
||||
fuse_fs_futimens(f->fs,fi,tv));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(!err && ((valid & (FATTR_ATIME|FATTR_MTIME)) == (FATTR_ATIME|FATTR_MTIME)))
|
||||
{
|
||||
pthread_mutex_lock(&f->lock);
|
||||
node = get_node(f,ino);
|
||||
if(node->is_hidden)
|
||||
{
|
||||
fi = &ffi;
|
||||
fi->fh = node->hidden_fh;
|
||||
}
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
struct timespec tv[2];
|
||||
tv[0].tv_sec = attr->st_atime;
|
||||
tv[0].tv_nsec = ST_ATIM_NSEC(attr);
|
||||
tv[1].tv_sec = attr->st_mtime;
|
||||
tv[1].tv_nsec = ST_MTIM_NSEC(attr);
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_utimens(f->fs,path,tv) :
|
||||
fuse_fs_futimens(f->fs,fi,tv));
|
||||
}
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
path = NULL;
|
||||
if(!err)
|
||||
err = ((fi == NULL) ?
|
||||
get_path(f,ino,&path) :
|
||||
get_path_nullok(f,ino,&path));
|
||||
fuse_fs_getattr(f->fs,path,&buf) :
|
||||
fuse_fs_fgetattr(f->fs,path,&buf,fi));
|
||||
|
||||
if (!err) {
|
||||
struct fuse_intr_data d;
|
||||
fuse_finish_interrupt(f,req,&d);
|
||||
free_path(f,ino,path);
|
||||
}
|
||||
|
||||
fuse_prepare_interrupt(f, req, &d);
|
||||
|
||||
err = 0;
|
||||
if (!err && (valid & FUSE_SET_ATTR_MODE))
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_chmod(f->fs, path, attr->st_mode) :
|
||||
fuse_fs_fchmod(f->fs, fi, attr->st_mode));
|
||||
|
||||
if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID)))
|
||||
{
|
||||
uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
|
||||
attr->st_uid : (uid_t) -1;
|
||||
gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
|
||||
attr->st_gid : (gid_t) -1;
|
||||
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_chown(f->fs, path, uid, gid) :
|
||||
fuse_fs_fchown(f->fs, fi, uid, gid));
|
||||
}
|
||||
|
||||
if (!err && (valid & FUSE_SET_ATTR_SIZE))
|
||||
{
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_truncate(f->fs, path, attr->st_size) :
|
||||
fuse_fs_ftruncate(f->fs, path, attr->st_size, fi));
|
||||
}
|
||||
#ifdef HAVE_UTIMENSAT
|
||||
if (!err && f->utime_omit_ok &&
|
||||
(valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
|
||||
struct timespec tv[2];
|
||||
|
||||
tv[0].tv_sec = 0;
|
||||
tv[1].tv_sec = 0;
|
||||
tv[0].tv_nsec = UTIME_OMIT;
|
||||
tv[1].tv_nsec = UTIME_OMIT;
|
||||
|
||||
if (valid & FUSE_SET_ATTR_ATIME_NOW)
|
||||
tv[0].tv_nsec = UTIME_NOW;
|
||||
else if (valid & FUSE_SET_ATTR_ATIME)
|
||||
tv[0] = attr->st_atim;
|
||||
|
||||
if (valid & FUSE_SET_ATTR_MTIME_NOW)
|
||||
tv[1].tv_nsec = UTIME_NOW;
|
||||
else if (valid & FUSE_SET_ATTR_MTIME)
|
||||
tv[1] = attr->st_mtim;
|
||||
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_utimens(f->fs, path, tv) :
|
||||
fuse_fs_futimens(f->fs, fi, tv));
|
||||
} else
|
||||
#endif
|
||||
if (!err &&
|
||||
(valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
|
||||
(FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
|
||||
struct timespec tv[2];
|
||||
tv[0].tv_sec = attr->st_atime;
|
||||
tv[0].tv_nsec = ST_ATIM_NSEC(attr);
|
||||
tv[1].tv_sec = attr->st_mtime;
|
||||
tv[1].tv_nsec = ST_MTIM_NSEC(attr);
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_utimens(f->fs, path, tv) :
|
||||
fuse_fs_futimens(f->fs, fi, tv));
|
||||
}
|
||||
|
||||
if (!err)
|
||||
err = ((fi == NULL) ?
|
||||
fuse_fs_getattr(f->fs, path, &buf) :
|
||||
fuse_fs_fgetattr(f->fs, path, &buf, fi));
|
||||
|
||||
fuse_finish_interrupt(f, req, &d);
|
||||
free_path(f, ino, path);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
pthread_mutex_lock(&f->lock);
|
||||
update_stat(get_node(f, ino), &buf);
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
set_stat(f, ino, &buf);
|
||||
fuse_reply_attr(req, &buf, f->conf.attr_timeout);
|
||||
} else {
|
||||
reply_err(req, err);
|
||||
}
|
||||
if(!err)
|
||||
{
|
||||
pthread_mutex_lock(&f->lock);
|
||||
update_stat(get_node(f,ino),&buf);
|
||||
pthread_mutex_unlock(&f->lock);
|
||||
set_stat(f,ino,&buf);
|
||||
fuse_reply_attr(req,&buf,f->conf.attr_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
reply_err(req,err);
|
||||
}
|
||||
}
|
||||
|
||||
static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask)
|
||||
|
@ -54,35 +54,43 @@ static __attribute__((constructor)) void fuse_ll_init_pagesize(void)
|
||||
pagesize = getpagesize();
|
||||
}
|
||||
|
||||
static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
|
||||
static
|
||||
void
|
||||
convert_stat(const struct stat *stbuf_,
|
||||
struct fuse_attr *attr_)
|
||||
{
|
||||
attr->ino = stbuf->st_ino;
|
||||
attr->mode = stbuf->st_mode;
|
||||
attr->nlink = stbuf->st_nlink;
|
||||
attr->uid = stbuf->st_uid;
|
||||
attr->gid = stbuf->st_gid;
|
||||
attr->rdev = stbuf->st_rdev;
|
||||
attr->size = stbuf->st_size;
|
||||
attr->blksize = stbuf->st_blksize;
|
||||
attr->blocks = stbuf->st_blocks;
|
||||
attr->atime = stbuf->st_atime;
|
||||
attr->mtime = stbuf->st_mtime;
|
||||
attr->ctime = stbuf->st_ctime;
|
||||
attr->atimensec = ST_ATIM_NSEC(stbuf);
|
||||
attr->mtimensec = ST_MTIM_NSEC(stbuf);
|
||||
attr->ctimensec = ST_CTIM_NSEC(stbuf);
|
||||
attr_->ino = stbuf_->st_ino;
|
||||
attr_->mode = stbuf_->st_mode;
|
||||
attr_->nlink = stbuf_->st_nlink;
|
||||
attr_->uid = stbuf_->st_uid;
|
||||
attr_->gid = stbuf_->st_gid;
|
||||
attr_->rdev = stbuf_->st_rdev;
|
||||
attr_->size = stbuf_->st_size;
|
||||
attr_->blksize = stbuf_->st_blksize;
|
||||
attr_->blocks = stbuf_->st_blocks;
|
||||
attr_->atime = stbuf_->st_atime;
|
||||
attr_->mtime = stbuf_->st_mtime;
|
||||
attr_->ctime = stbuf_->st_ctime;
|
||||
attr_->atimensec = ST_ATIM_NSEC(stbuf_);
|
||||
attr_->mtimensec = ST_MTIM_NSEC(stbuf_);
|
||||
attr_->ctimensec = ST_CTIM_NSEC(stbuf_);
|
||||
}
|
||||
|
||||
static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
|
||||
static
|
||||
void
|
||||
convert_attr(const struct fuse_setattr_in *attr_,
|
||||
struct stat *stbuf_)
|
||||
{
|
||||
stbuf->st_mode = attr->mode;
|
||||
stbuf->st_uid = attr->uid;
|
||||
stbuf->st_gid = attr->gid;
|
||||
stbuf->st_size = attr->size;
|
||||
stbuf->st_atime = attr->atime;
|
||||
stbuf->st_mtime = attr->mtime;
|
||||
ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
|
||||
ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
|
||||
stbuf_->st_mode = attr_->mode;
|
||||
stbuf_->st_uid = attr_->uid;
|
||||
stbuf_->st_gid = attr_->gid;
|
||||
stbuf_->st_size = attr_->size;
|
||||
stbuf_->st_atime = attr_->atime;
|
||||
stbuf_->st_mtime = attr_->mtime;
|
||||
stbuf_->st_ctime = attr_->ctime;
|
||||
ST_ATIM_NSEC_SET(stbuf_,attr_->atimensec);
|
||||
ST_MTIM_NSEC_SET(stbuf_,attr_->mtimensec);
|
||||
ST_CTIM_NSEC_SET(stbuf_,attr_->ctimensec);
|
||||
}
|
||||
|
||||
static size_t iov_length(const struct iovec *iov, size_t count)
|
||||
@ -297,9 +305,11 @@ static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
|
||||
return send_reply(req, 0, arg, argsize);
|
||||
}
|
||||
|
||||
int fuse_reply_err(fuse_req_t req, int err)
|
||||
int
|
||||
fuse_reply_err(fuse_req_t req_,
|
||||
int err_)
|
||||
{
|
||||
return send_reply(req, -err, NULL, 0);
|
||||
return send_reply(req_,-err_,NULL,0);
|
||||
}
|
||||
|
||||
void fuse_reply_none(fuse_req_t req)
|
||||
@ -1053,35 +1063,46 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
}
|
||||
|
||||
static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
static
|
||||
void
|
||||
do_setattr(fuse_req_t req_,
|
||||
fuse_ino_t nodeid_,
|
||||
const void *inarg_)
|
||||
{
|
||||
struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
|
||||
struct stat stbuf;
|
||||
struct fuse_file_info *fi;
|
||||
struct fuse_file_info fi_store;
|
||||
struct fuse_setattr_in *arg;
|
||||
|
||||
if (req->f->op.setattr) {
|
||||
struct fuse_file_info *fi = NULL;
|
||||
struct fuse_file_info fi_store;
|
||||
struct stat stbuf;
|
||||
memset(&stbuf, 0, sizeof(stbuf));
|
||||
convert_attr(arg, &stbuf);
|
||||
if (arg->valid & FATTR_FH) {
|
||||
arg->valid &= ~FATTR_FH;
|
||||
memset(&fi_store, 0, sizeof(fi_store));
|
||||
fi = &fi_store;
|
||||
fi->fh = arg->fh;
|
||||
}
|
||||
arg->valid &=
|
||||
FUSE_SET_ATTR_MODE |
|
||||
FUSE_SET_ATTR_UID |
|
||||
FUSE_SET_ATTR_GID |
|
||||
FUSE_SET_ATTR_SIZE |
|
||||
FUSE_SET_ATTR_ATIME |
|
||||
FUSE_SET_ATTR_MTIME |
|
||||
FUSE_SET_ATTR_ATIME_NOW |
|
||||
FUSE_SET_ATTR_MTIME_NOW;
|
||||
if(req_->f->op.setattr == NULL)
|
||||
return (void)fuse_reply_err(req_,ENOSYS);
|
||||
|
||||
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
|
||||
} else
|
||||
fuse_reply_err(req, ENOSYS);
|
||||
fi = NULL;
|
||||
arg = (struct fuse_setattr_in*)inarg_;
|
||||
|
||||
memset(&stbuf,0,sizeof(stbuf));
|
||||
convert_attr(arg,&stbuf);
|
||||
|
||||
if(arg->valid & FATTR_FH)
|
||||
{
|
||||
arg->valid &= ~FATTR_FH;
|
||||
memset(&fi_store,0,sizeof(fi_store));
|
||||
fi = &fi_store;
|
||||
fi->fh = arg->fh;
|
||||
}
|
||||
|
||||
arg->valid &=
|
||||
(FATTR_MODE |
|
||||
FATTR_UID |
|
||||
FATTR_GID |
|
||||
FATTR_SIZE |
|
||||
FATTR_ATIME |
|
||||
FATTR_MTIME |
|
||||
FATTR_CTIME |
|
||||
FATTR_ATIME_NOW |
|
||||
FATTR_MTIME_NOW);
|
||||
|
||||
req_->f->op.setattr(req_,nodeid_,&stbuf,arg->valid,fi);
|
||||
}
|
||||
|
||||
static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
|
||||
|
@ -36,22 +36,25 @@ static inline void fuse_mutex_init(pthread_mutex_t *mut)
|
||||
|
||||
#ifdef HAVE_STRUCT_STAT_ST_ATIM
|
||||
/* Linux */
|
||||
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
|
||||
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
|
||||
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
|
||||
#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atim.tv_nsec = (val)
|
||||
#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtim.tv_nsec = (val)
|
||||
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
|
||||
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
|
||||
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
|
||||
#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atim.tv_nsec = (val))
|
||||
#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctim.tv_nsec = (val))
|
||||
#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtim.tv_nsec = (val))
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
|
||||
/* FreeBSD */
|
||||
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec)
|
||||
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec)
|
||||
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec)
|
||||
#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimespec.tv_nsec = (val)
|
||||
#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimespec.tv_nsec = (val)
|
||||
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec)
|
||||
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec)
|
||||
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec)
|
||||
#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atimespec.tv_nsec = (val))
|
||||
#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctimespec.tv_nsec = (val))
|
||||
#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtimespec.tv_nsec = (val))
|
||||
#else
|
||||
#define ST_ATIM_NSEC(stbuf) 0
|
||||
#define ST_CTIM_NSEC(stbuf) 0
|
||||
#define ST_MTIM_NSEC(stbuf) 0
|
||||
#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0)
|
||||
#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0)
|
||||
#define ST_ATIM_NSEC_SET(stbuf,val) do { } while (0)
|
||||
#define ST_CTIM_NSEC_SET(stbuf,val) do { } while (0)
|
||||
#define ST_MTIM_NSEC_SET(stbuf,val) do { } while (0)
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user