Browse Source

Merge pull request #706 from trapexit/ctime

ctime
pull/710/head
trapexit 5 years ago
committed by GitHub
parent
commit
43ddff6ca9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 76
      libfuse/include/fuse_kernel.h
  2. 10
      libfuse/include/fuse_lowlevel.h
  3. 96
      libfuse/lib/fuse.c
  4. 127
      libfuse/lib/fuse_lowlevel.c
  5. 15
      libfuse/lib/fuse_misc.h

76
libfuse/include/fuse_kernel.h

@ -38,12 +38,50 @@
*
* Protocol changelog:
*
* 7.1:
* - add the following messages:
* FUSE_SETATTR, FUSE_SYMLINK, FUSE_MKNOD, FUSE_MKDIR, FUSE_UNLINK,
* FUSE_RMDIR, FUSE_RENAME, FUSE_LINK, FUSE_OPEN, FUSE_READ, FUSE_WRITE,
* FUSE_RELEASE, FUSE_FSYNC, FUSE_FLUSH, FUSE_SETXATTR, FUSE_GETXATTR,
* FUSE_LISTXATTR, FUSE_REMOVEXATTR, FUSE_OPENDIR, FUSE_READDIR,
* FUSE_RELEASEDIR
* - add padding to messages to accommodate 32-bit servers on 64-bit kernels
*
* 7.2:
* - add FOPEN_DIRECT_IO and FOPEN_KEEP_CACHE flags
* - add FUSE_FSYNCDIR message
*
* 7.3:
* - add FUSE_ACCESS message
* - add FUSE_CREATE message
* - add filehandle to fuse_setattr_in
*
* 7.4:
* - add frsize to fuse_kstatfs
* - clean up request size limit checking
*
* 7.5:
* - add flags and max_write to fuse_init_out
*
* 7.6:
* - add max_readahead to fuse_init_in and fuse_init_out
*
* 7.7:
* - add FUSE_INTERRUPT message
* - add POSIX file lock support
*
* 7.8:
* - add lock_owner and flags fields to fuse_release_in
* - add FUSE_BMAP message
* - add FUSE_DESTROY message
*
* 7.9:
* - new fuse_getattr_in input argument of GETATTR
* - add lk_flags in fuse_lk_in
* - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
* - add blksize field to fuse_attr
* - add file flags field to fuse_read_in and fuse_write_in
* - Add ATIME_NOW and MTIME_NOW flags to fuse_setattr_in
*
* 7.10
* - add nonseekable open flag
@ -54,7 +92,7 @@
* - add POLL message and NOTIFY_POLL notification
*
* 7.12
* - add umask flag to input argument of open, mknod and mkdir
* - add umask flag to input argument of create, mknod and mkdir
* - add notification messages for invalidation of inodes and
* directory entries
*
@ -125,6 +163,15 @@
*
* 7.29
* - add FUSE_NO_OPENDIR_SUPPORT flag
*
* 7.30
* - add FUSE_EXPLICIT_INVAL_DATA
* - add FUSE_IOCTL_COMPAT_X32
*
* 7.31
* - add FUSE_WRITE_KILL_PRIV flag
* - add FUSE_SETUPMAPPING and FUSE_REMOVEMAPPING
* - add map_alignment to fuse_init_out, add FUSE_MAP_ALIGNMENT flag
*/
#ifndef _LINUX_FUSE_H
@ -160,7 +207,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 29
#define FUSE_KERNEL_MINOR_VERSION 31
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@ -229,11 +276,13 @@ struct fuse_file_lock {
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
* FOPEN_NONSEEKABLE: the file is not seekable
* FOPEN_CACHE_DIR: allow caching this directory
* FOPEN_STREAM: the file is stream-like (no file position at all)
*/
#define FOPEN_DIRECT_IO (1 << 0)
#define FOPEN_KEEP_CACHE (1 << 1)
#define FOPEN_NONSEEKABLE (1 << 2)
#define FOPEN_CACHE_DIR (1 << 3)
#define FOPEN_STREAM (1 << 4)
/**
* INIT request/reply flags
@ -263,6 +312,8 @@ struct fuse_file_lock {
* FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
* FUSE_CACHE_SYMLINKS: cache READLINK responses
* FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir
* FUSE_EXPLICIT_INVAL_DATA: only invalidate cached pages on explicit request
* FUSE_MAP_ALIGNMENT: map_alignment field is valid
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@ -289,6 +340,8 @@ struct fuse_file_lock {
#define FUSE_MAX_PAGES (1 << 22)
#define FUSE_CACHE_SYMLINKS (1 << 23)
#define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
#define FUSE_EXPLICIT_INVAL_DATA (1 << 25)
#define FUSE_MAP_ALIGNMENT (1 << 26)
/**
* CUSE INIT request/reply flags
@ -318,9 +371,11 @@ struct fuse_file_lock {
*
* FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
* FUSE_WRITE_LOCKOWNER: lock_owner field is valid
* FUSE_WRITE_KILL_PRIV: kill suid and sgid bits
*/
#define FUSE_WRITE_CACHE (1 << 0)
#define FUSE_WRITE_LOCKOWNER (1 << 1)
#define FUSE_WRITE_KILL_PRIV (1 << 2)
/**
* Read flags
@ -335,6 +390,7 @@ struct fuse_file_lock {
* FUSE_IOCTL_RETRY: retry with new iovecs
* FUSE_IOCTL_32BIT: 32bit ioctl
* FUSE_IOCTL_DIR: is a directory
* FUSE_IOCTL_COMPAT_X32: x32 compat ioctl on 64bit machine (64bit time_t)
*
* FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs
*/
@ -343,6 +399,7 @@ struct fuse_file_lock {
#define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_32BIT (1 << 3)
#define FUSE_IOCTL_DIR (1 << 4)
#define FUSE_IOCTL_COMPAT_X32 (1 << 5)
#define FUSE_IOCTL_MAX_IOV 256
@ -353,6 +410,13 @@ struct fuse_file_lock {
*/
#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
/**
* Fsync flags
*
* FUSE_FSYNC_FDATASYNC: Sync data only, not metadata
*/
#define FUSE_FSYNC_FDATASYNC (1 << 0)
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
@ -399,9 +463,15 @@ enum fuse_opcode {
FUSE_RENAME2 = 45,
FUSE_LSEEK = 46,
FUSE_COPY_FILE_RANGE = 47,
FUSE_SETUPMAPPING = 48,
FUSE_REMOVEMAPPING = 49,
/* CUSE specific operations */
CUSE_INIT = 4096,
/* Reserved opcodes: helpful to detect structure endian-ness */
CUSE_INIT_BSWAP_RESERVED = 1048576, /* CUSE_INIT << 8 */
FUSE_INIT_BSWAP_RESERVED = 436207616, /* FUSE_INIT << 24 */
};
enum fuse_notify_code {
@ -629,7 +699,7 @@ struct fuse_init_out {
uint32_t max_write;
uint32_t time_gran;
uint16_t max_pages;
uint16_t padding;
uint16_t map_alignment;
uint32_t unused[8];
};

10
libfuse/include/fuse_lowlevel.h

@ -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 *
* ----------------------------------------------------------- */

96
libfuse/lib/fuse.c

@ -2735,8 +2735,13 @@ 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;
@ -2757,45 +2762,43 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
pthread_mutex_unlock(&f->lock);
}
memset(&buf, 0, sizeof(buf));
memset(&buf,0,sizeof(buf));
path = NULL;
err = ((fi == NULL) ?
get_path(f,ino,&path) :
get_path_nullok(f,ino,&path));
if (!err) {
if(!err)
{
struct fuse_intr_data d;
fuse_prepare_interrupt(f, req, &d);
fuse_prepare_interrupt(f,req,&d);
err = 0;
if (!err && (valid & FUSE_SET_ATTR_MODE))
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));
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)))
if(!err && (valid & (FATTR_UID | FATTR_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;
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));
fuse_fs_chown(f->fs,path,uid,gid) :
fuse_fs_fchown(f->fs,fi,uid,gid));
}
if (!err && (valid & FUSE_SET_ATTR_SIZE))
{
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));
}
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))) {
if(!err && f->utime_omit_ok && (valid & (FATTR_ATIME | FATTR_MTIME)))
{
struct timespec tv[2];
tv[0].tv_sec = 0;
@ -2803,51 +2806,54 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
tv[0].tv_nsec = UTIME_OMIT;
tv[1].tv_nsec = UTIME_OMIT;
if (valid & FUSE_SET_ATTR_ATIME_NOW)
if(valid & FATTR_ATIME_NOW)
tv[0].tv_nsec = UTIME_NOW;
else if (valid & FUSE_SET_ATTR_ATIME)
else if(valid & FATTR_ATIME)
tv[0] = attr->st_atim;
if (valid & FUSE_SET_ATTR_MTIME_NOW)
if(valid & FATTR_MTIME_NOW)
tv[1].tv_nsec = UTIME_NOW;
else if (valid & FUSE_SET_ATTR_MTIME)
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
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)) {
if(!err && ((valid & (FATTR_ATIME|FATTR_MTIME)) == (FATTR_ATIME|FATTR_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));
fuse_fs_utimens(f->fs,path,tv) :
fuse_fs_futimens(f->fs,fi,tv));
}
if (!err)
if(!err)
err = ((fi == NULL) ?
fuse_fs_getattr(f->fs, path, &buf) :
fuse_fs_fgetattr(f->fs, path, &buf, fi));
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);
fuse_finish_interrupt(f,req,&d);
free_path(f,ino,path);
}
if (!err) {
if(!err)
{
pthread_mutex_lock(&f->lock);
update_stat(get_node(f, ino), &buf);
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);
set_stat(f,ino,&buf);
fuse_reply_attr(req,&buf,f->conf.attr_timeout);
}
else
{
reply_err(req,err);
}
}

127
libfuse/lib/fuse_lowlevel.c

@ -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)
{
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)
{
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);
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_);
}
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;
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;
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) {
struct fuse_file_info *fi;
struct fuse_file_info fi_store;
struct fuse_setattr_in *arg;
if(req_->f->op.setattr == NULL)
return (void)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));
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;
req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
} else
fuse_reply_err(req, ENOSYS);
(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)

15
libfuse/lib/fuse_misc.h

@ -39,19 +39,22 @@ static inline void fuse_mutex_init(pthread_mutex_t *mut)
#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_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_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…
Cancel
Save