diff options
author | Niels de Vos <ndevos@redhat.com> | 2017-01-07 14:23:40 +0100 |
---|---|---|
committer | Kaleb KEITHLEY <kkeithle@redhat.com> | 2017-01-08 17:10:59 -0800 |
commit | 068e4f345f51438d252b1e330ca7049bd4a67e03 (patch) | |
tree | 77545637257de138a283710f59e519507683d3da | |
parent | 268a1c1100ca661095d5606d0248e038bdbefd49 (diff) |
posix: make sure atime and mtime are set when calling lutimes()
When overwriting an existing file with O_TRUNC, the 'atime' was set to
0, meaning the Epoch (01-Jan-1970 UTC). However, the 'mtime' gets
updated correcty.
In case 'atime' or 'mtime' is not passed in the 'struct iatt', the time
values passed to the systemcall are taken from the current values are
returned by lstat().
Cherry picked from commit 9bed81ada6f91f998e9abd915b18e3f06557cdcb:
> Change-Id: I7021b7161dcd6c9a3e515d98f6d4847533c434b3
> BUG: 1401777
> Reported-by: Eivind Sarto <eivindsarto@gmail.com>
> Signed-off-by: Niels de Vos <ndevos@redhat.com>
> Reviewed-on: http://review.gluster.org/16034
> Smoke: Gluster Build System <jenkins@build.gluster.org>
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
> Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Change-Id: I7021b7161dcd6c9a3e515d98f6d4847533c434b3
BUG: 1411011
Reported-by: Eivind Sarto <eivindsarto@gmail.com>
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/16356
Smoke: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
-rw-r--r-- | libglusterfs/src/compat.h | 12 | ||||
-rwxr-xr-x | tests/bugs/nfs/zero-atime.t | 31 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 26 |
3 files changed, 63 insertions, 6 deletions
diff --git a/libglusterfs/src/compat.h b/libglusterfs/src/compat.h index ea722028eb5..fbaac76b9ee 100644 --- a/libglusterfs/src/compat.h +++ b/libglusterfs/src/compat.h @@ -444,6 +444,12 @@ int gf_mkostemp (char *tmpl, int suffixlen, int flags); #ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC /* Linux, Solaris, Cygwin */ +#define ST_ATIM_SEC(stbuf) ((stbuf)->st_atim.tv_sec) +#define ST_CTIM_SEC(stbuf) ((stbuf)->st_ctim.tv_sec) +#define ST_MTIM_SEC(stbuf) ((stbuf)->st_mtim.tv_sec) +#define ST_ATIM_SEC_SET(stbuf, val) ((stbuf)->st_atim.tv_sec = (val)) +#define ST_MTIM_SEC_SET(stbuf, val) ((stbuf)->st_mtim.tv_sec = (val)) +#define ST_CTIM_SEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_sec = (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) @@ -452,6 +458,12 @@ int gf_mkostemp (char *tmpl, int suffixlen, int flags); #define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_nsec = (val)) #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC) /* FreeBSD, NetBSD */ +#define ST_ATIM_SEC(stbuf) ((stbuf)->st_atimespec.tv_sec) +#define ST_CTIM_SEC(stbuf) ((stbuf)->st_ctimespec.tv_sec) +#define ST_MTIM_SEC(stbuf) ((stbuf)->st_mtimespec.tv_sec) +#define ST_ATIM_SEC_SET(stbuf, val) ((stbuf)->st_atimespec.tv_sec = (val)) +#define ST_MTIM_SEC_SET(stbuf, val) ((stbuf)->st_mtimespec.tv_sec = (val)) +#define ST_CTIM_SEC_SET(stbuf, val) ((stbuf)->st_ctimespec.tv_sec = (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) diff --git a/tests/bugs/nfs/zero-atime.t b/tests/bugs/nfs/zero-atime.t new file mode 100755 index 00000000000..631240a692f --- /dev/null +++ b/tests/bugs/nfs/zero-atime.t @@ -0,0 +1,31 @@ +#!/bin/bash +# +# posix_do_utimes() sets atime and mtime to the values in the passed IATT. If +# not set, these values are 0 and cause a atime/mtime set to the Epoch. +# + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../nfs.rc + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 +TEST $CLI volume set $V0 nfs.disable false +TEST $CLI volume start $V0 +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available; +TEST mount_nfs $H0:/$V0 $N0 nolock + +# create a file for testing +TEST dd if=/dev/urandom of=$M0/small count=1 bs=1024k + +# timezone in UTC results in atime=0 if not set correctly +TEST TZ=UTC dd if=/dev/urandom of=$M0/small bs=64k count=1 conv=nocreat +TEST [ "$(stat --format=%X $M0/small)" != "0" ] + +TEST rm $M0/small + +cleanup diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index cecf5dcb66d..2c51d1967a8 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -374,7 +374,8 @@ posix_do_chown (xlator_t *this, static int posix_do_utimes (xlator_t *this, const char *path, - struct iatt *stbuf) + struct iatt *stbuf, + int valid) { int32_t ret = -1; struct timeval tv[2] = {{0,},{0,}}; @@ -391,10 +392,23 @@ posix_do_utimes (xlator_t *this, if (S_ISLNK (stat.st_mode)) is_symlink = 1; - tv[0].tv_sec = stbuf->ia_atime; - tv[0].tv_usec = stbuf->ia_atime_nsec / 1000; - tv[1].tv_sec = stbuf->ia_mtime; - tv[1].tv_usec = stbuf->ia_mtime_nsec / 1000; + if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { + tv[0].tv_sec = stbuf->ia_atime; + tv[0].tv_usec = stbuf->ia_atime_nsec / 1000; + } else { + /* atime is not given, use current values */ + tv[0].tv_sec = ST_ATIM_SEC (&stat); + tv[0].tv_usec = ST_ATIM_NSEC (&stat) / 1000; + } + + if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { + tv[1].tv_sec = stbuf->ia_mtime; + tv[1].tv_usec = stbuf->ia_mtime_nsec / 1000; + } else { + /* mtime is not given, use current values */ + tv[1].tv_sec = ST_MTIM_SEC (&stat); + tv[1].tv_usec = ST_MTIM_NSEC (&stat) / 1000; + } ret = lutimes (path, tv); if ((ret == -1) && (errno == ENOSYS)) { @@ -463,7 +477,7 @@ posix_setattr (call_frame_t *frame, xlator_t *this, } if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { - op_ret = posix_do_utimes (this, real_path, stbuf); + op_ret = posix_do_utimes (this, real_path, stbuf, valid); if (op_ret == -1) { op_errno = errno; gf_msg (this->name, GF_LOG_ERROR, errno, |