summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
authorNiklas Hambüchen <mail@nh2.me>2017-02-18 00:49:02 +0100
committerJeff Darcy <jdarcy@redhat.com>2017-03-07 12:10:02 -0500
commitce8d8195dc253a87cceaaeeb1a725090471ae4f8 (patch)
tree87c027440d7a6af44956861b34fec3844d699038 /libglusterfs
parent89c6bedc1c2e978f67ca29f212a357984cd8a2dd (diff)
posix: use nanosecond accuracy when available
Programs that set mtime, such as `rsync -a`, don't work correctly on GlusterFS, because it sets the nanoseconds to 000. This creates problems for incremental backups, where files get accidentally copied again and again. For example, consider `myfile` on an ext4 system, being copied to a GlusterFS volume, with `rsync -a` and then `cp -u` in turn. You'd expect that after the first `rsync -a`, `cp -u` agrees that the file need not be copied. BUG: 1422074 Change-Id: I89c7b6a73e2e06c02851ff76b7e5cdfaa271e985 Signed-off-by: Niklas Hambüchen <mail@nh2.me> Reviewed-on: https://review.gluster.org/16667 Smoke: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Niels de Vos <ndevos@redhat.com> Tested-by: Jeff Darcy <jdarcy@redhat.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: jiffin tony Thottan <jthottan@redhat.com> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/common-utils.c28
-rw-r--r--libglusterfs/src/libglusterfs-messages.h11
-rw-r--r--libglusterfs/src/syscall.c10
-rw-r--r--libglusterfs/src/syscall.h6
4 files changed, 49 insertions, 6 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index 51f97442fec..e18c97f5aa1 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -3806,7 +3806,11 @@ int
gf_set_timestamp (const char *src, const char* dest)
{
struct stat sb = {0, };
- struct timeval new_time[2] = {{0, },{0,}};
+#if defined(HAVE_UTIMENSAT)
+ struct timespec new_time[2] = { {0, }, {0, } };
+#else
+ struct timeval new_time[2] = { {0, }, {0, } };
+#endif
int ret = 0;
xlator_t *this = NULL;
@@ -3821,21 +3825,35 @@ gf_set_timestamp (const char *src, const char* dest)
LG_MSG_FILE_STAT_FAILED, "stat on %s", src);
goto out;
}
+ /* The granularity is nano seconds if `utimensat()` is available,
+ * and micro seconds otherwise.
+ */
+#if defined(HAVE_UTIMENSAT)
+ new_time[0].tv_sec = sb.st_atime;
+ new_time[0].tv_nsec = ST_ATIM_NSEC (&sb);
+
+ new_time[1].tv_sec = sb.st_mtime;
+ new_time[1].tv_nsec = ST_MTIM_NSEC (&sb);
+
+ /* dirfd = 0 is ignored because `dest` is an absolute path. */
+ ret = sys_utimensat (AT_FDCWD, dest, new_time, AT_SYMLINK_NOFOLLOW);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ LG_MSG_UTIMENSAT_FAILED, "utimensat on %s", dest);
+ }
+#else
new_time[0].tv_sec = sb.st_atime;
new_time[0].tv_usec = ST_ATIM_NSEC (&sb)/1000;
new_time[1].tv_sec = sb.st_mtime;
new_time[1].tv_usec = ST_MTIM_NSEC (&sb)/1000;
- /* The granularity is micro seconds as per the current
- * requiremnt. Hence using 'utimes'. This can be updated
- * to 'utimensat' if we need timestamp in nanoseconds.
- */
ret = sys_utimes (dest, new_time);
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, errno, LG_MSG_UTIMES_FAILED,
"utimes on %s", dest);
}
+#endif
out:
return ret;
}
diff --git a/libglusterfs/src/libglusterfs-messages.h b/libglusterfs/src/libglusterfs-messages.h
index 29196929eb3..23ed7b727d3 100644
--- a/libglusterfs/src/libglusterfs-messages.h
+++ b/libglusterfs/src/libglusterfs-messages.h
@@ -37,7 +37,7 @@
#define GLFS_LG_BASE GLFS_MSGID_COMP_LIBGLUSTERFS
-#define GLFS_LG_NUM_MESSAGES 209
+#define GLFS_LG_NUM_MESSAGES 210
#define GLFS_LG_MSGID_END (GLFS_LG_BASE + GLFS_LG_NUM_MESSAGES + 1)
/* Messaged with message IDs */
@@ -1791,6 +1791,15 @@
* @recommendedaction
*
*/
+
+#define LG_MSG_UTIMENSAT_FAILED (GLFS_LG_BASE + 210)
+
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ *
+ */
/*------------*/
#define glfs_msg_end_lg GLFS_LG_MSGID_END, "Invalid: End of messages"
diff --git a/libglusterfs/src/syscall.c b/libglusterfs/src/syscall.c
index 4e4c6a728da..a7d4402808d 100644
--- a/libglusterfs/src/syscall.c
+++ b/libglusterfs/src/syscall.c
@@ -272,6 +272,16 @@ sys_utimes (const char *filename, const struct timeval times[2])
}
+#if defined(HAVE_UTIMENSAT)
+int
+sys_utimensat (int dirfd, const char *filename, const struct timespec times[2],
+ int flags)
+{
+ return utimensat (dirfd, filename, times, flags);
+}
+#endif
+
+
int
sys_creat (const char *pathname, mode_t mode)
{
diff --git a/libglusterfs/src/syscall.h b/libglusterfs/src/syscall.h
index b1bcad138c5..6bb374822ee 100644
--- a/libglusterfs/src/syscall.h
+++ b/libglusterfs/src/syscall.h
@@ -129,6 +129,12 @@ sys_ftruncate (int fd, off_t length);
int
sys_utimes (const char *filename, const struct timeval times[2]);
+#if defined(HAVE_UTIMENSAT)
+int
+sys_utimensat (int dirfd, const char *filename, const struct timespec times[2],
+ int flags);
+#endif
+
int
sys_creat (const char *pathname, mode_t mode);