e3c68b
From 55eb2e7642e3428eaa1b2d833c0daa1d34b98324 Mon Sep 17 00:00:00 2001
e3c68b
From: Kotresh HR <khiremat@redhat.com>
e3c68b
Date: Thu, 8 Aug 2019 10:05:12 +0530
e3c68b
Subject: [PATCH 283/284] ctime: Fix ctime issue with utime family of syscalls
e3c68b
e3c68b
When atime|mtime is updated via utime family of syscalls,
e3c68b
ctime is not updated. This patch fixes the same.
e3c68b
e3c68b
Backport of:
e3c68b
 > Patch: https://review.gluster.org/23177
e3c68b
 > Change-Id: I7f86d8f8a1e06a332c3449b5bbdbf128c9690f25
e3c68b
 > fixes: bz#1738786
e3c68b
 > Signed-off-by: Kotresh HR <khiremat@redhat.com>
e3c68b
e3c68b
Change-Id: I7f86d8f8a1e06a332c3449b5bbdbf128c9690f25
e3c68b
BUG: 1743627
e3c68b
Signed-off-by: Kotresh HR <khiremat@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/179184
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e3c68b
---
e3c68b
 xlators/features/utime/src/utime-gen-fops-c.py | 13 +++-
e3c68b
 xlators/storage/posix/src/posix-inode-fd-ops.c |  8 +--
e3c68b
 xlators/storage/posix/src/posix-metadata.c     | 96 ++++++++++++++------------
e3c68b
 xlators/storage/posix/src/posix-metadata.h     |  3 +-
e3c68b
 4 files changed, 68 insertions(+), 52 deletions(-)
e3c68b
e3c68b
diff --git a/xlators/features/utime/src/utime-gen-fops-c.py b/xlators/features/utime/src/utime-gen-fops-c.py
e3c68b
index a8637ff..8730a51 100755
e3c68b
--- a/xlators/features/utime/src/utime-gen-fops-c.py
e3c68b
+++ b/xlators/features/utime/src/utime-gen-fops-c.py
e3c68b
@@ -82,7 +82,18 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this,
e3c68b
              @LONG_ARGS@)
e3c68b
 {
e3c68b
         gl_timespec_get(&frame->root->ctime);
e3c68b
-        frame->root->flags |= MDATA_CTIME;
e3c68b
+
e3c68b
+        if (!valid) {
e3c68b
+                frame->root->flags |= MDATA_CTIME;
e3c68b
+        }
e3c68b
+
e3c68b
+        if (valid & (GF_SET_ATTR_UID | GF_SET_ATTR_GID)) {
e3c68b
+                frame->root->flags |= MDATA_CTIME;
e3c68b
+        }
e3c68b
+
e3c68b
+        if (valid & GF_SET_ATTR_MODE) {
e3c68b
+                frame->root->flags |= MDATA_CTIME;
e3c68b
+        }
e3c68b
 
e3c68b
         STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this),
e3c68b
                     FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@);
e3c68b
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
index d22bbc2..e0ea85b 100644
e3c68b
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
e3c68b
@@ -425,8 +425,8 @@ posix_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
e3c68b
                    real_path);
e3c68b
             goto out;
e3c68b
         }
e3c68b
-        posix_update_utime_in_mdata(this, real_path, -1, loc->inode, stbuf,
e3c68b
-                                    valid);
e3c68b
+        posix_update_utime_in_mdata(this, real_path, -1, loc->inode,
e3c68b
+                                    &frame->root->ctime, stbuf, valid);
e3c68b
     }
e3c68b
 
e3c68b
     if (valid & GF_SET_ATTR_CTIME && !priv->ctime) {
e3c68b
@@ -652,8 +652,8 @@ posix_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd,
e3c68b
                    fd);
e3c68b
             goto out;
e3c68b
         }
e3c68b
-        posix_update_utime_in_mdata(this, NULL, pfd->fd, fd->inode, stbuf,
e3c68b
-                                    valid);
e3c68b
+        posix_update_utime_in_mdata(this, NULL, pfd->fd, fd->inode,
e3c68b
+                                    &frame->root->ctime, stbuf, valid);
e3c68b
     }
e3c68b
 
e3c68b
     if (!valid) {
e3c68b
diff --git a/xlators/storage/posix/src/posix-metadata.c b/xlators/storage/posix/src/posix-metadata.c
e3c68b
index 5cbdc98..532daa2 100644
e3c68b
--- a/xlators/storage/posix/src/posix-metadata.c
e3c68b
+++ b/xlators/storage/posix/src/posix-metadata.c
e3c68b
@@ -432,8 +432,10 @@ out:
e3c68b
  */
e3c68b
 static int
e3c68b
 posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd,
e3c68b
-                      inode_t *inode, struct timespec *time, struct iatt *stbuf,
e3c68b
-                      posix_mdata_flag_t *flag, gf_boolean_t update_utime)
e3c68b
+                      inode_t *inode, struct timespec *time,
e3c68b
+                      struct timespec *u_atime, struct timespec *u_mtime,
e3c68b
+                      struct iatt *stbuf, posix_mdata_flag_t *flag,
e3c68b
+                      gf_boolean_t update_utime)
e3c68b
 {
e3c68b
     posix_mdata_t *mdata = NULL;
e3c68b
     int ret = -1;
e3c68b
@@ -443,6 +445,10 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd,
e3c68b
     GF_VALIDATE_OR_GOTO(this->name, inode, out);
e3c68b
     GF_VALIDATE_OR_GOTO(this->name, time, out);
e3c68b
 
e3c68b
+    if (update_utime && (!u_atime || !u_mtime)) {
e3c68b
+        goto out;
e3c68b
+    }
e3c68b
+
e3c68b
     LOCK(&inode->lock);
e3c68b
     {
e3c68b
         ret = __inode_ctx_get1(inode, this, (uint64_t *)&mdata);
e3c68b
@@ -506,32 +512,30 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd,
e3c68b
             }
e3c68b
         }
e3c68b
 
e3c68b
-        /* Earlier, mdata was updated only if the existing time is less
e3c68b
-         * than the time to be updated. This would fail the scenarios
e3c68b
-         * where mtime can be set to any time using the syscall. Hence
e3c68b
-         * just updating without comparison. But the ctime is not
e3c68b
-         * allowed to changed to older date.
e3c68b
-         */
e3c68b
-
e3c68b
-        if (flag->ctime && posix_compare_timespec(time, &mdata->ctime) > 0) {
e3c68b
-            mdata->ctime = *time;
e3c68b
-        }
e3c68b
-
e3c68b
         /* In distributed systems, there could be races with fops
e3c68b
          * updating mtime/atime which could result in different
e3c68b
          * mtime/atime for same file. So this makes sure, only the
e3c68b
          * highest time is retained. If the mtime/atime update comes
e3c68b
          * from the explicit utime syscall, it is allowed to set to
e3c68b
-         * previous time
e3c68b
+         * previous or future time but the ctime is always set to
e3c68b
+         * current time.
e3c68b
          */
e3c68b
         if (update_utime) {
e3c68b
+            if (flag->ctime &&
e3c68b
+                posix_compare_timespec(time, &mdata->ctime) > 0) {
e3c68b
+                mdata->ctime = *time;
e3c68b
+            }
e3c68b
             if (flag->mtime) {
e3c68b
-                mdata->mtime = *time;
e3c68b
+                mdata->mtime = *u_mtime;
e3c68b
             }
e3c68b
             if (flag->atime) {
e3c68b
-                mdata->atime = *time;
e3c68b
+                mdata->atime = *u_atime;
e3c68b
             }
e3c68b
         } else {
e3c68b
+            if (flag->ctime &&
e3c68b
+                posix_compare_timespec(time, &mdata->ctime) > 0) {
e3c68b
+                mdata->ctime = *time;
e3c68b
+            }
e3c68b
             if (flag->mtime &&
e3c68b
                 posix_compare_timespec(time, &mdata->mtime) > 0) {
e3c68b
                 mdata->mtime = *time;
e3c68b
@@ -584,15 +588,22 @@ out:
e3c68b
  */
e3c68b
 void
e3c68b
 posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
-                            inode_t *inode, struct iatt *stbuf, int valid)
e3c68b
+                            inode_t *inode, struct timespec *ctime,
e3c68b
+                            struct iatt *stbuf, int valid)
e3c68b
 {
e3c68b
     int32_t ret = 0;
e3c68b
 #if defined(HAVE_UTIMENSAT)
e3c68b
-    struct timespec tv = {
e3c68b
+    struct timespec tv_atime = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+    struct timespec tv_mtime = {
e3c68b
         0,
e3c68b
     };
e3c68b
 #else
e3c68b
-    struct timeval tv = {
e3c68b
+    struct timeval tv_atime = {
e3c68b
+        0,
e3c68b
+    };
e3c68b
+    struct timeval tv_mtime = {
e3c68b
         0,
e3c68b
     };
e3c68b
 #endif
e3c68b
@@ -611,35 +622,28 @@ posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
      */
e3c68b
     if (inode && priv->ctime) {
e3c68b
         if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) {
e3c68b
-            tv.tv_sec = stbuf->ia_atime;
e3c68b
-            SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, stbuf->ia_atime_nsec);
e3c68b
+            tv_atime.tv_sec = stbuf->ia_atime;
e3c68b
+            SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_atime, stbuf->ia_atime_nsec);
e3c68b
 
e3c68b
-            flag.ctime = 0;
e3c68b
-            flag.mtime = 0;
e3c68b
+            flag.ctime = 1;
e3c68b
             flag.atime = 1;
e3c68b
-            ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv, NULL,
e3c68b
-                                        &flag, _gf_true);
e3c68b
-            if (ret) {
e3c68b
-                gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
-                       "posix set mdata atime failed on file:"
e3c68b
-                       " %s gfid:%s",
e3c68b
-                       real_path, uuid_utoa(inode->gfid));
e3c68b
-            }
e3c68b
         }
e3c68b
 
e3c68b
         if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) {
e3c68b
-            tv.tv_sec = stbuf->ia_mtime;
e3c68b
-            SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, stbuf->ia_mtime_nsec);
e3c68b
+            tv_mtime.tv_sec = stbuf->ia_mtime;
e3c68b
+            SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_mtime, stbuf->ia_mtime_nsec);
e3c68b
 
e3c68b
-            flag.ctime = 0;
e3c68b
+            flag.ctime = 1;
e3c68b
             flag.mtime = 1;
e3c68b
-            flag.atime = 0;
e3c68b
+        }
e3c68b
 
e3c68b
-            ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv, NULL,
e3c68b
-                                        &flag, _gf_true);
e3c68b
+        if (flag.mtime || flag.atime) {
e3c68b
+            ret = posix_set_mdata_xattr(this, real_path, -1, inode, ctime,
e3c68b
+                                        &tv_atime, &tv_mtime, NULL, &flag,
e3c68b
+                                        _gf_true);
e3c68b
             if (ret) {
e3c68b
                 gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
-                       "posix set mdata mtime failed on file:"
e3c68b
+                       "posix set mdata atime failed on file:"
e3c68b
                        " %s gfid:%s",
e3c68b
                        real_path, uuid_utoa(inode->gfid));
e3c68b
             }
e3c68b
@@ -702,8 +706,8 @@ posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path,
e3c68b
             goto out;
e3c68b
         }
e3c68b
         ret = posix_set_mdata_xattr(this, real_path, fd, inode,
e3c68b
-                                    &frame->root->ctime, stbuf, &flag,
e3c68b
-                                    _gf_false);
e3c68b
+                                    &frame->root->ctime, NULL, NULL, stbuf,
e3c68b
+                                    &flag, _gf_false);
e3c68b
         if (ret) {
e3c68b
             gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
                    "posix set mdata failed on file: %s gfid:%s", real_path,
e3c68b
@@ -733,8 +737,8 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this,
e3c68b
             goto out;
e3c68b
         }
e3c68b
         ret = posix_set_mdata_xattr(this, real_path, fd, inode,
e3c68b
-                                    &frame->root->ctime, stbuf, &flag,
e3c68b
-                                    _gf_false);
e3c68b
+                                    &frame->root->ctime, NULL, NULL, stbuf,
e3c68b
+                                    &flag, _gf_false);
e3c68b
         if (ret) {
e3c68b
             gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
                    "posix set mdata failed on file: %s gfid:%s", real_path,
e3c68b
@@ -792,8 +796,8 @@ posix_set_ctime_cfr(call_frame_t *frame, xlator_t *this,
e3c68b
             flag_dup.atime = 0;
e3c68b
 
e3c68b
         ret = posix_set_mdata_xattr(this, real_path_out, fd_out, inode_out,
e3c68b
-                                    &frame->root->ctime, stbuf_out, &flag_dup,
e3c68b
-                                    _gf_false);
e3c68b
+                                    &frame->root->ctime, NULL, NULL, stbuf_out,
e3c68b
+                                    &flag_dup, _gf_false);
e3c68b
         if (ret) {
e3c68b
             gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
                    "posix set mdata failed on file: %s gfid:%s", real_path_out,
e3c68b
@@ -811,8 +815,8 @@ posix_set_ctime_cfr(call_frame_t *frame, xlator_t *this,
e3c68b
         flag_dup.ctime = 0;
e3c68b
 
e3c68b
         ret = posix_set_mdata_xattr(this, real_path_in, fd_out, inode_out,
e3c68b
-                                    &frame->root->ctime, stbuf_out, &flag_dup,
e3c68b
-                                    _gf_false);
e3c68b
+                                    &frame->root->ctime, NULL, NULL, stbuf_out,
e3c68b
+                                    &flag_dup, _gf_false);
e3c68b
         if (ret) {
e3c68b
             gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
e3c68b
                    "posix set mdata failed on file: %s gfid:%s", real_path_in,
e3c68b
diff --git a/xlators/storage/posix/src/posix-metadata.h b/xlators/storage/posix/src/posix-metadata.h
e3c68b
index dc25e59..c176699 100644
e3c68b
--- a/xlators/storage/posix/src/posix-metadata.h
e3c68b
+++ b/xlators/storage/posix/src/posix-metadata.h
e3c68b
@@ -40,7 +40,8 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd,
e3c68b
                         inode_t *inode, struct iatt *stbuf);
e3c68b
 void
e3c68b
 posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd,
e3c68b
-                            inode_t *inode, struct iatt *stbuf, int valid);
e3c68b
+                            inode_t *inode, struct timespec *ctime,
e3c68b
+                            struct iatt *stbuf, int valid);
e3c68b
 void
e3c68b
 posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path,
e3c68b
                 int fd, inode_t *inode, struct iatt *stbuf);
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b