[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <E1NN4MD-0005ZG-7M@pomaz-ex.szeredi.hu>
Date: Tue, 22 Dec 2009 14:00:57 +0100
From: Miklos Szeredi <miklos@...redi.hu>
To: Jean-Pierre André <jean-pierre.andre@...adoo.fr>
CC: hirofumi@...l.parknet.co.jp, ebb9@....net,
fuse-devel@...ts.sourceforge.net, miklos@...redi.hu, hch@....de,
linux-kernel@...r.kernel.org, xfs@....sgi.com
Subject: Re: [fuse-devel] utimensat fails to update ctime
On Tue, 22 Dec 2009, Jean-Pierre André wrote:
> With ntfs-3g this is not directly possible, because
> the interface does not provide flags telling which
> timestamps should be updated. The only way would
> be fuse feeding both values (even though unchanged)
> before calling ntfs-3g. This is true for all versions of
> ntfs-3g.
Here's a patch for the high level lib. If the flag_utime_omit_ok flag
is set then the ->utimes() method will be supplied with arguments that
correspond to utimensat (i.e. it can have UTIME_NOW and UTIME_OMIT
values).
Thanks,
Miklos
Index: fuse/configure.in
===================================================================
--- fuse.orig/configure.in 2009-12-22 12:46:44.000000000 +0100
+++ fuse/configure.in 2009-12-22 13:16:07.000000000 +0100
@@ -53,7 +53,7 @@ fi
if test "$enable_mtab" = "no"; then
AC_DEFINE(IGNORE_MTAB, 1, [Don't update /etc/mtab])
fi
-AC_CHECK_FUNCS([fork setxattr fdatasync])
+AC_CHECK_FUNCS([fork setxattr fdatasync utimensat])
AC_CHECK_MEMBERS([struct stat.st_atim])
AC_CHECK_MEMBERS([struct stat.st_atimespec])
Index: fuse/include/fuse.h
===================================================================
--- fuse.orig/include/fuse.h 2009-12-22 12:46:44.000000000 +0100
+++ fuse/include/fuse.h 2009-12-22 13:16:07.000000000 +0100
@@ -458,9 +458,15 @@ struct fuse_operations {
unsigned int flag_nullpath_ok : 1;
/**
+ * Flag indicating that the filesystem accepts special
+ * UTIME_NOW and UTIME_OMIT values in its utimens operation.
+ */
+ unsigned int flag_utime_omit_ok : 1;
+
+ /**
* Reserved flags, don't set
*/
- unsigned int flag_reserved : 31;
+ unsigned int flag_reserved : 30;
/**
* Ioctl
Index: fuse/lib/fuse.c
===================================================================
--- fuse.orig/lib/fuse.c 2009-12-22 12:46:44.000000000 +0100
+++ fuse/lib/fuse.c 2009-12-22 13:16:07.000000000 +0100
@@ -97,6 +97,7 @@ struct fuse {
int intr_installed;
struct fuse_fs *fs;
int nullpath_ok;
+ int utime_omit_ok;
int curr_ticket;
struct lock_queue_element *lockq;
};
@@ -2119,6 +2120,29 @@ static void fuse_lib_setattr(fuse_req_t
err = fuse_fs_truncate(f->fs, path,
attr->st_size);
}
+#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 = fuse_fs_utimens(f->fs, path, tv);
+ } else
+#endif
if (!err &&
(valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ==
(FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
@@ -3637,6 +3661,7 @@ static int fuse_push_module(struct fuse
newfs->m = m;
f->fs = newfs;
f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
+ f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
return 0;
}
@@ -3687,6 +3712,7 @@ struct fuse *fuse_new_common(struct fuse
fs->compat = compat;
f->fs = fs;
f->nullpath_ok = fs->op.flag_nullpath_ok;
+ f->utime_omit_ok = fs->op.flag_utime_omit_ok;
/* Oh f**k, this is ugly! */
if (!fs->op.lock) {
@@ -3743,8 +3769,10 @@ struct fuse *fuse_new_common(struct fuse
fuse_session_add_chan(f->se, ch);
- if (f->conf.debug)
+ if (f->conf.debug) {
fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
+ fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
+ }
/* Trace topmost layer by default */
f->fs->debug = f->conf.debug;
Index: fuse/example/fusexmp_fh.c
===================================================================
--- fuse.orig/example/fusexmp_fh.c 2009-06-19 12:24:25.000000000 +0200
+++ fuse/example/fusexmp_fh.c 2009-12-22 13:55:04.000000000 +0100
@@ -283,6 +283,9 @@ static int xmp_ftruncate(const char *pat
static int xmp_utimens(const char *path, const struct timespec ts[2])
{
int res;
+#ifdef HAVE_UTIMENSAT
+ res = utimensat(AT_FDCWD, path, ts, AT_SYMLINK_NOFOLLOW);
+#else
struct timeval tv[2];
tv[0].tv_sec = ts[0].tv_sec;
@@ -291,6 +294,7 @@ static int xmp_utimens(const char *path,
tv[1].tv_usec = ts[1].tv_nsec / 1000;
res = utimes(path, tv);
+#endif
if (res == -1)
return -errno;
@@ -486,6 +490,9 @@ static struct fuse_operations xmp_oper =
.lock = xmp_lock,
.flag_nullpath_ok = 1,
+#if HAVE_UTIMENSAT
+ .flag_utime_omit_ok = 1,
+#endif
};
int main(int argc, char *argv[])
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists