diff options
| author | Niklas Hambüchen <mail@nh2.me> | 2017-02-18 00:49:02 +0100 | 
|---|---|---|
| committer | Jeff Darcy <jdarcy@redhat.com> | 2017-03-07 12:10:02 -0500 | 
| commit | ce8d8195dc253a87cceaaeeb1a725090471ae4f8 (patch) | |
| tree | 87c027440d7a6af44956861b34fec3844d699038 /libglusterfs/src | |
| parent | 89c6bedc1c2e978f67ca29f212a357984cd8a2dd (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/src')
| -rw-r--r-- | libglusterfs/src/common-utils.c | 28 | ||||
| -rw-r--r-- | libglusterfs/src/libglusterfs-messages.h | 11 | ||||
| -rw-r--r-- | libglusterfs/src/syscall.c | 10 | ||||
| -rw-r--r-- | libglusterfs/src/syscall.h | 6 | 
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);  | 
